12e192b24SSimon Glass /* 22e192b24SSimon Glass * Copyright 2015 Freescale Semiconductor, Inc. 32e192b24SSimon Glass * 42e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 52e192b24SSimon Glass * 62e192b24SSimon Glass * Ethernet Switch commands 72e192b24SSimon Glass */ 82e192b24SSimon Glass 92e192b24SSimon Glass #include <common.h> 102e192b24SSimon Glass #include <command.h> 11*9925f1dbSAlex Kiernan #include <environment.h> 122e192b24SSimon Glass #include <errno.h> 132e192b24SSimon Glass #include <env_flags.h> 142e192b24SSimon Glass #include <ethsw.h> 152e192b24SSimon Glass 162e192b24SSimon Glass static const char *ethsw_name; 172e192b24SSimon Glass 182e192b24SSimon Glass #define ETHSW_PORT_STATS_HELP "ethsw [port <port_no>] statistics " \ 192e192b24SSimon Glass "{ [help] | [clear] } - show an l2 switch port's statistics" 202e192b24SSimon Glass 212e192b24SSimon Glass static int ethsw_port_stats_help_key_func(struct ethsw_command_def *parsed_cmd) 222e192b24SSimon Glass { 232e192b24SSimon Glass printf(ETHSW_PORT_STATS_HELP"\n"); 242e192b24SSimon Glass 252e192b24SSimon Glass return CMD_RET_SUCCESS; 262e192b24SSimon Glass } 272e192b24SSimon Glass 282e192b24SSimon Glass #define ETHSW_LEARN_HELP "ethsw [port <port_no>] learning " \ 292e192b24SSimon Glass "{ [help] | show | auto | disable } " \ 302e192b24SSimon Glass "- enable/disable/show learning configuration on a port" 312e192b24SSimon Glass 322e192b24SSimon Glass static int ethsw_learn_help_key_func(struct ethsw_command_def *parsed_cmd) 332e192b24SSimon Glass { 342e192b24SSimon Glass printf(ETHSW_LEARN_HELP"\n"); 352e192b24SSimon Glass 362e192b24SSimon Glass return CMD_RET_SUCCESS; 372e192b24SSimon Glass } 382e192b24SSimon Glass 392e192b24SSimon Glass #define ETHSW_FDB_HELP "ethsw [port <port_no>] [vlan <vid>] fdb " \ 402e192b24SSimon Glass "{ [help] | show | flush | { add | del } <mac> } " \ 412e192b24SSimon Glass "- Add/delete a mac entry in FDB; use show to see FDB entries; " \ 422e192b24SSimon Glass "if vlan <vid> is missing, VID 1 will be used" 432e192b24SSimon Glass 442e192b24SSimon Glass static int ethsw_fdb_help_key_func(struct ethsw_command_def *parsed_cmd) 452e192b24SSimon Glass { 462e192b24SSimon Glass printf(ETHSW_FDB_HELP"\n"); 472e192b24SSimon Glass 482e192b24SSimon Glass return CMD_RET_SUCCESS; 492e192b24SSimon Glass } 502e192b24SSimon Glass 512e192b24SSimon Glass #define ETHSW_PVID_HELP "ethsw [port <port_no>] " \ 522e192b24SSimon Glass "pvid { [help] | show | <pvid> } " \ 532e192b24SSimon Glass "- set/show PVID (ingress and egress VLAN tagging) for a port" 542e192b24SSimon Glass 552e192b24SSimon Glass static int ethsw_pvid_help_key_func(struct ethsw_command_def *parsed_cmd) 562e192b24SSimon Glass { 572e192b24SSimon Glass printf(ETHSW_PVID_HELP"\n"); 582e192b24SSimon Glass 592e192b24SSimon Glass return CMD_RET_SUCCESS; 602e192b24SSimon Glass } 612e192b24SSimon Glass 622e192b24SSimon Glass #define ETHSW_VLAN_HELP "ethsw [port <port_no>] vlan " \ 632e192b24SSimon Glass "{ [help] | show | add <vid> | del <vid> } " \ 642e192b24SSimon Glass "- add a VLAN to a port (VLAN members)" 652e192b24SSimon Glass 662e192b24SSimon Glass static int ethsw_vlan_help_key_func(struct ethsw_command_def *parsed_cmd) 672e192b24SSimon Glass { 682e192b24SSimon Glass printf(ETHSW_VLAN_HELP"\n"); 692e192b24SSimon Glass 702e192b24SSimon Glass return CMD_RET_SUCCESS; 712e192b24SSimon Glass } 722e192b24SSimon Glass 732e192b24SSimon Glass #define ETHSW_PORT_UNTAG_HELP "ethsw [port <port_no>] untagged " \ 742e192b24SSimon Glass "{ [help] | show | all | none | pvid } " \ 7582d72a1bSTom Rini " - set egress tagging mode for a port" 762e192b24SSimon Glass 772e192b24SSimon Glass static int ethsw_port_untag_help_key_func(struct ethsw_command_def *parsed_cmd) 782e192b24SSimon Glass { 792e192b24SSimon Glass printf(ETHSW_PORT_UNTAG_HELP"\n"); 802e192b24SSimon Glass 812e192b24SSimon Glass return CMD_RET_SUCCESS; 822e192b24SSimon Glass } 832e192b24SSimon Glass 842e192b24SSimon Glass #define ETHSW_EGR_VLAN_TAG_HELP "ethsw [port <port_no>] egress tag " \ 852e192b24SSimon Glass "{ [help] | show | pvid | classified } " \ 862e192b24SSimon Glass "- Configure VID source for egress tag. " \ 872e192b24SSimon Glass "Tag's VID could be the frame's classified VID or the PVID of the port" 882e192b24SSimon Glass 892e192b24SSimon Glass static int ethsw_egr_tag_help_key_func(struct ethsw_command_def *parsed_cmd) 902e192b24SSimon Glass { 912e192b24SSimon Glass printf(ETHSW_EGR_VLAN_TAG_HELP"\n"); 922e192b24SSimon Glass 932e192b24SSimon Glass return CMD_RET_SUCCESS; 942e192b24SSimon Glass } 952e192b24SSimon Glass 962e192b24SSimon Glass #define ETHSW_VLAN_FDB_HELP "ethsw vlan fdb " \ 972e192b24SSimon Glass "{ [help] | show | shared | private } " \ 982e192b24SSimon Glass "- make VLAN learning shared or private" 992e192b24SSimon Glass 1002e192b24SSimon Glass static int ethsw_vlan_learn_help_key_func(struct ethsw_command_def *parsed_cmd) 1012e192b24SSimon Glass { 1022e192b24SSimon Glass printf(ETHSW_VLAN_FDB_HELP"\n"); 1032e192b24SSimon Glass 1042e192b24SSimon Glass return CMD_RET_SUCCESS; 1052e192b24SSimon Glass } 1062e192b24SSimon Glass 1072e192b24SSimon Glass #define ETHSW_PORT_INGR_FLTR_HELP "ethsw [port <port_no>] ingress filtering" \ 1082e192b24SSimon Glass " { [help] | show | enable | disable } " \ 1092e192b24SSimon Glass "- enable/disable VLAN ingress filtering on port" 1102e192b24SSimon Glass 1112e192b24SSimon Glass static int ethsw_ingr_fltr_help_key_func(struct ethsw_command_def *parsed_cmd) 1122e192b24SSimon Glass { 1132e192b24SSimon Glass printf(ETHSW_PORT_INGR_FLTR_HELP"\n"); 1142e192b24SSimon Glass 1152e192b24SSimon Glass return CMD_RET_SUCCESS; 1162e192b24SSimon Glass } 1172e192b24SSimon Glass 11882d72a1bSTom Rini #define ETHSW_PORT_AGGR_HELP "ethsw [port <port_no>] aggr" \ 11982d72a1bSTom Rini " { [help] | show | <lag_group_no> } " \ 12082d72a1bSTom Rini "- get/set LAG group for a port" 12182d72a1bSTom Rini 12282d72a1bSTom Rini static int ethsw_port_aggr_help_key_func(struct ethsw_command_def *parsed_cmd) 12382d72a1bSTom Rini { 12482d72a1bSTom Rini printf(ETHSW_PORT_AGGR_HELP"\n"); 12582d72a1bSTom Rini 12682d72a1bSTom Rini return CMD_RET_SUCCESS; 12782d72a1bSTom Rini } 12882d72a1bSTom Rini 1292e192b24SSimon Glass static struct keywords_to_function { 1302e192b24SSimon Glass enum ethsw_keyword_id cmd_keyword[ETHSW_MAX_CMD_PARAMS]; 1312e192b24SSimon Glass int cmd_func_offset; 1322e192b24SSimon Glass int (*keyword_function)(struct ethsw_command_def *parsed_cmd); 1332e192b24SSimon Glass } ethsw_cmd_def[] = { 1342e192b24SSimon Glass { 1352e192b24SSimon Glass .cmd_keyword = { 1362e192b24SSimon Glass ethsw_id_enable, 1372e192b24SSimon Glass ethsw_id_key_end, 1382e192b24SSimon Glass }, 1392e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 1402e192b24SSimon Glass port_enable), 1412e192b24SSimon Glass .keyword_function = NULL, 1422e192b24SSimon Glass }, { 1432e192b24SSimon Glass .cmd_keyword = { 1442e192b24SSimon Glass ethsw_id_disable, 1452e192b24SSimon Glass ethsw_id_key_end, 1462e192b24SSimon Glass }, 1472e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 1482e192b24SSimon Glass port_disable), 1492e192b24SSimon Glass .keyword_function = NULL, 1502e192b24SSimon Glass }, { 1512e192b24SSimon Glass .cmd_keyword = { 1522e192b24SSimon Glass ethsw_id_show, 1532e192b24SSimon Glass ethsw_id_key_end, 1542e192b24SSimon Glass }, 1552e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 1562e192b24SSimon Glass port_show), 1572e192b24SSimon Glass .keyword_function = NULL, 1582e192b24SSimon Glass }, { 1592e192b24SSimon Glass .cmd_keyword = { 1602e192b24SSimon Glass ethsw_id_statistics, 1612e192b24SSimon Glass ethsw_id_help, 1622e192b24SSimon Glass ethsw_id_key_end, 1632e192b24SSimon Glass }, 1642e192b24SSimon Glass .cmd_func_offset = -1, 1652e192b24SSimon Glass .keyword_function = ðsw_port_stats_help_key_func, 1662e192b24SSimon Glass }, { 1672e192b24SSimon Glass .cmd_keyword = { 1682e192b24SSimon Glass ethsw_id_statistics, 1692e192b24SSimon Glass ethsw_id_key_end, 1702e192b24SSimon Glass }, 1712e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 1722e192b24SSimon Glass port_stats), 1732e192b24SSimon Glass .keyword_function = NULL, 1742e192b24SSimon Glass }, { 1752e192b24SSimon Glass .cmd_keyword = { 1762e192b24SSimon Glass ethsw_id_statistics, 1772e192b24SSimon Glass ethsw_id_clear, 1782e192b24SSimon Glass ethsw_id_key_end, 1792e192b24SSimon Glass }, 1802e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 1812e192b24SSimon Glass port_stats_clear), 1822e192b24SSimon Glass .keyword_function = NULL, 1832e192b24SSimon Glass }, { 1842e192b24SSimon Glass .cmd_keyword = { 1852e192b24SSimon Glass ethsw_id_learning, 1862e192b24SSimon Glass ethsw_id_key_end, 1872e192b24SSimon Glass }, 1882e192b24SSimon Glass .cmd_func_offset = -1, 1892e192b24SSimon Glass .keyword_function = ðsw_learn_help_key_func, 1902e192b24SSimon Glass }, { 1912e192b24SSimon Glass .cmd_keyword = { 1922e192b24SSimon Glass ethsw_id_learning, 1932e192b24SSimon Glass ethsw_id_help, 1942e192b24SSimon Glass ethsw_id_key_end, 1952e192b24SSimon Glass }, 1962e192b24SSimon Glass .cmd_func_offset = -1, 1972e192b24SSimon Glass .keyword_function = ðsw_learn_help_key_func, 1982e192b24SSimon Glass }, { 1992e192b24SSimon Glass .cmd_keyword = { 2002e192b24SSimon Glass ethsw_id_learning, 2012e192b24SSimon Glass ethsw_id_show, 2022e192b24SSimon Glass ethsw_id_key_end, 2032e192b24SSimon Glass }, 2042e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 2052e192b24SSimon Glass port_learn_show), 2062e192b24SSimon Glass .keyword_function = NULL, 2072e192b24SSimon Glass }, { 2082e192b24SSimon Glass .cmd_keyword = { 2092e192b24SSimon Glass ethsw_id_learning, 2102e192b24SSimon Glass ethsw_id_auto, 2112e192b24SSimon Glass ethsw_id_key_end, 2122e192b24SSimon Glass }, 2132e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 2142e192b24SSimon Glass port_learn), 2152e192b24SSimon Glass .keyword_function = NULL, 2162e192b24SSimon Glass }, { 2172e192b24SSimon Glass .cmd_keyword = { 2182e192b24SSimon Glass ethsw_id_learning, 2192e192b24SSimon Glass ethsw_id_disable, 2202e192b24SSimon Glass ethsw_id_key_end, 2212e192b24SSimon Glass }, 2222e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 2232e192b24SSimon Glass port_learn), 2242e192b24SSimon Glass .keyword_function = NULL, 2252e192b24SSimon Glass }, { 2262e192b24SSimon Glass .cmd_keyword = { 2272e192b24SSimon Glass ethsw_id_fdb, 2282e192b24SSimon Glass ethsw_id_key_end, 2292e192b24SSimon Glass }, 2302e192b24SSimon Glass .cmd_func_offset = -1, 2312e192b24SSimon Glass .keyword_function = ðsw_fdb_help_key_func, 2322e192b24SSimon Glass }, { 2332e192b24SSimon Glass .cmd_keyword = { 2342e192b24SSimon Glass ethsw_id_fdb, 2352e192b24SSimon Glass ethsw_id_help, 2362e192b24SSimon Glass ethsw_id_key_end, 2372e192b24SSimon Glass }, 2382e192b24SSimon Glass .cmd_func_offset = -1, 2392e192b24SSimon Glass .keyword_function = ðsw_fdb_help_key_func, 2402e192b24SSimon Glass }, { 2412e192b24SSimon Glass .cmd_keyword = { 2422e192b24SSimon Glass ethsw_id_fdb, 2432e192b24SSimon Glass ethsw_id_show, 2442e192b24SSimon Glass ethsw_id_key_end, 2452e192b24SSimon Glass }, 2462e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 2472e192b24SSimon Glass fdb_show), 2482e192b24SSimon Glass .keyword_function = NULL, 2492e192b24SSimon Glass }, { 2502e192b24SSimon Glass .cmd_keyword = { 2512e192b24SSimon Glass ethsw_id_fdb, 2522e192b24SSimon Glass ethsw_id_flush, 2532e192b24SSimon Glass ethsw_id_key_end, 2542e192b24SSimon Glass }, 2552e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 2562e192b24SSimon Glass fdb_flush), 2572e192b24SSimon Glass .keyword_function = NULL, 2582e192b24SSimon Glass }, { 2592e192b24SSimon Glass .cmd_keyword = { 2602e192b24SSimon Glass ethsw_id_fdb, 2612e192b24SSimon Glass ethsw_id_add, 2622e192b24SSimon Glass ethsw_id_add_del_mac, 2632e192b24SSimon Glass ethsw_id_key_end, 2642e192b24SSimon Glass }, 2652e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 2662e192b24SSimon Glass fdb_entry_add), 2672e192b24SSimon Glass .keyword_function = NULL, 2682e192b24SSimon Glass }, { 2692e192b24SSimon Glass .cmd_keyword = { 2702e192b24SSimon Glass ethsw_id_fdb, 2712e192b24SSimon Glass ethsw_id_del, 2722e192b24SSimon Glass ethsw_id_add_del_mac, 2732e192b24SSimon Glass ethsw_id_key_end, 2742e192b24SSimon Glass }, 2752e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 2762e192b24SSimon Glass fdb_entry_del), 2772e192b24SSimon Glass .keyword_function = NULL, 2782e192b24SSimon Glass }, { 2792e192b24SSimon Glass .cmd_keyword = { 2802e192b24SSimon Glass ethsw_id_pvid, 2812e192b24SSimon Glass ethsw_id_key_end, 2822e192b24SSimon Glass }, 2832e192b24SSimon Glass .cmd_func_offset = -1, 2842e192b24SSimon Glass .keyword_function = ðsw_pvid_help_key_func, 2852e192b24SSimon Glass }, { 2862e192b24SSimon Glass .cmd_keyword = { 2872e192b24SSimon Glass ethsw_id_pvid, 2882e192b24SSimon Glass ethsw_id_help, 2892e192b24SSimon Glass ethsw_id_key_end, 2902e192b24SSimon Glass }, 2912e192b24SSimon Glass .cmd_func_offset = -1, 2922e192b24SSimon Glass .keyword_function = ðsw_pvid_help_key_func, 2932e192b24SSimon Glass }, { 2942e192b24SSimon Glass .cmd_keyword = { 2952e192b24SSimon Glass ethsw_id_pvid, 2962e192b24SSimon Glass ethsw_id_show, 2972e192b24SSimon Glass ethsw_id_key_end, 2982e192b24SSimon Glass }, 2992e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 3002e192b24SSimon Glass pvid_show), 3012e192b24SSimon Glass .keyword_function = NULL, 3022e192b24SSimon Glass }, { 3032e192b24SSimon Glass .cmd_keyword = { 3042e192b24SSimon Glass ethsw_id_pvid, 3052e192b24SSimon Glass ethsw_id_pvid_no, 3062e192b24SSimon Glass ethsw_id_key_end, 3072e192b24SSimon Glass }, 3082e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 3092e192b24SSimon Glass pvid_set), 3102e192b24SSimon Glass .keyword_function = NULL, 3112e192b24SSimon Glass }, { 3122e192b24SSimon Glass .cmd_keyword = { 3132e192b24SSimon Glass ethsw_id_vlan, 3142e192b24SSimon Glass ethsw_id_key_end, 3152e192b24SSimon Glass }, 3162e192b24SSimon Glass .cmd_func_offset = -1, 3172e192b24SSimon Glass .keyword_function = ðsw_vlan_help_key_func, 3182e192b24SSimon Glass }, { 3192e192b24SSimon Glass .cmd_keyword = { 3202e192b24SSimon Glass ethsw_id_vlan, 3212e192b24SSimon Glass ethsw_id_help, 3222e192b24SSimon Glass ethsw_id_key_end, 3232e192b24SSimon Glass }, 3242e192b24SSimon Glass .cmd_func_offset = -1, 3252e192b24SSimon Glass .keyword_function = ðsw_vlan_help_key_func, 3262e192b24SSimon Glass }, { 3272e192b24SSimon Glass .cmd_keyword = { 3282e192b24SSimon Glass ethsw_id_vlan, 3292e192b24SSimon Glass ethsw_id_show, 3302e192b24SSimon Glass ethsw_id_key_end, 3312e192b24SSimon Glass }, 3322e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 3332e192b24SSimon Glass vlan_show), 3342e192b24SSimon Glass .keyword_function = NULL, 3352e192b24SSimon Glass }, { 3362e192b24SSimon Glass .cmd_keyword = { 3372e192b24SSimon Glass ethsw_id_vlan, 3382e192b24SSimon Glass ethsw_id_add, 3392e192b24SSimon Glass ethsw_id_add_del_no, 3402e192b24SSimon Glass ethsw_id_key_end, 3412e192b24SSimon Glass }, 3422e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 3432e192b24SSimon Glass vlan_set), 3442e192b24SSimon Glass .keyword_function = NULL, 3452e192b24SSimon Glass }, { 3462e192b24SSimon Glass .cmd_keyword = { 3472e192b24SSimon Glass ethsw_id_vlan, 3482e192b24SSimon Glass ethsw_id_del, 3492e192b24SSimon Glass ethsw_id_add_del_no, 3502e192b24SSimon Glass ethsw_id_key_end, 3512e192b24SSimon Glass }, 3522e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 3532e192b24SSimon Glass vlan_set), 3542e192b24SSimon Glass .keyword_function = NULL, 3552e192b24SSimon Glass }, { 3562e192b24SSimon Glass .cmd_keyword = { 3572e192b24SSimon Glass ethsw_id_untagged, 3582e192b24SSimon Glass ethsw_id_key_end, 3592e192b24SSimon Glass }, 3602e192b24SSimon Glass .cmd_func_offset = -1, 3612e192b24SSimon Glass .keyword_function = ðsw_port_untag_help_key_func, 3622e192b24SSimon Glass }, { 3632e192b24SSimon Glass .cmd_keyword = { 3642e192b24SSimon Glass ethsw_id_untagged, 3652e192b24SSimon Glass ethsw_id_help, 3662e192b24SSimon Glass ethsw_id_key_end, 3672e192b24SSimon Glass }, 3682e192b24SSimon Glass .cmd_func_offset = -1, 3692e192b24SSimon Glass .keyword_function = ðsw_port_untag_help_key_func, 3702e192b24SSimon Glass }, { 3712e192b24SSimon Glass .cmd_keyword = { 3722e192b24SSimon Glass ethsw_id_untagged, 3732e192b24SSimon Glass ethsw_id_show, 3742e192b24SSimon Glass ethsw_id_key_end, 3752e192b24SSimon Glass }, 3762e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 3772e192b24SSimon Glass port_untag_show), 3782e192b24SSimon Glass .keyword_function = NULL, 3792e192b24SSimon Glass }, { 3802e192b24SSimon Glass .cmd_keyword = { 3812e192b24SSimon Glass ethsw_id_untagged, 3822e192b24SSimon Glass ethsw_id_all, 3832e192b24SSimon Glass ethsw_id_key_end, 3842e192b24SSimon Glass }, 3852e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 3862e192b24SSimon Glass port_untag_set), 3872e192b24SSimon Glass .keyword_function = NULL, 3882e192b24SSimon Glass }, { 3892e192b24SSimon Glass .cmd_keyword = { 3902e192b24SSimon Glass ethsw_id_untagged, 3912e192b24SSimon Glass ethsw_id_none, 3922e192b24SSimon Glass ethsw_id_key_end, 3932e192b24SSimon Glass }, 3942e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 3952e192b24SSimon Glass port_untag_set), 3962e192b24SSimon Glass .keyword_function = NULL, 3972e192b24SSimon Glass }, { 3982e192b24SSimon Glass .cmd_keyword = { 3992e192b24SSimon Glass ethsw_id_untagged, 4002e192b24SSimon Glass ethsw_id_pvid, 4012e192b24SSimon Glass ethsw_id_key_end, 4022e192b24SSimon Glass }, 4032e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 4042e192b24SSimon Glass port_untag_set), 4052e192b24SSimon Glass .keyword_function = NULL, 4062e192b24SSimon Glass }, { 4072e192b24SSimon Glass .cmd_keyword = { 4082e192b24SSimon Glass ethsw_id_egress, 4092e192b24SSimon Glass ethsw_id_tag, 4102e192b24SSimon Glass ethsw_id_key_end, 4112e192b24SSimon Glass }, 4122e192b24SSimon Glass .cmd_func_offset = -1, 4132e192b24SSimon Glass .keyword_function = ðsw_egr_tag_help_key_func, 4142e192b24SSimon Glass }, { 4152e192b24SSimon Glass .cmd_keyword = { 4162e192b24SSimon Glass ethsw_id_egress, 4172e192b24SSimon Glass ethsw_id_tag, 4182e192b24SSimon Glass ethsw_id_help, 4192e192b24SSimon Glass ethsw_id_key_end, 4202e192b24SSimon Glass }, 4212e192b24SSimon Glass .cmd_func_offset = -1, 4222e192b24SSimon Glass .keyword_function = ðsw_egr_tag_help_key_func, 4232e192b24SSimon Glass }, { 4242e192b24SSimon Glass .cmd_keyword = { 4252e192b24SSimon Glass ethsw_id_egress, 4262e192b24SSimon Glass ethsw_id_tag, 4272e192b24SSimon Glass ethsw_id_show, 4282e192b24SSimon Glass ethsw_id_key_end, 4292e192b24SSimon Glass }, 4302e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 4312e192b24SSimon Glass port_egr_vlan_show), 4322e192b24SSimon Glass .keyword_function = NULL, 4332e192b24SSimon Glass }, { 4342e192b24SSimon Glass .cmd_keyword = { 4352e192b24SSimon Glass ethsw_id_egress, 4362e192b24SSimon Glass ethsw_id_tag, 4372e192b24SSimon Glass ethsw_id_pvid, 4382e192b24SSimon Glass ethsw_id_key_end, 4392e192b24SSimon Glass }, 4402e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 4412e192b24SSimon Glass port_egr_vlan_set), 4422e192b24SSimon Glass .keyword_function = NULL, 4432e192b24SSimon Glass }, { 4442e192b24SSimon Glass .cmd_keyword = { 4452e192b24SSimon Glass ethsw_id_egress, 4462e192b24SSimon Glass ethsw_id_tag, 4472e192b24SSimon Glass ethsw_id_classified, 4482e192b24SSimon Glass ethsw_id_key_end, 4492e192b24SSimon Glass }, 4502e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 4512e192b24SSimon Glass port_egr_vlan_set), 4522e192b24SSimon Glass .keyword_function = NULL, 4532e192b24SSimon Glass }, { 4542e192b24SSimon Glass .cmd_keyword = { 4552e192b24SSimon Glass ethsw_id_vlan, 4562e192b24SSimon Glass ethsw_id_fdb, 4572e192b24SSimon Glass ethsw_id_key_end, 4582e192b24SSimon Glass }, 4592e192b24SSimon Glass .cmd_func_offset = -1, 4602e192b24SSimon Glass .keyword_function = ðsw_vlan_learn_help_key_func, 4612e192b24SSimon Glass }, { 4622e192b24SSimon Glass .cmd_keyword = { 4632e192b24SSimon Glass ethsw_id_vlan, 4642e192b24SSimon Glass ethsw_id_fdb, 4652e192b24SSimon Glass ethsw_id_help, 4662e192b24SSimon Glass ethsw_id_key_end, 4672e192b24SSimon Glass }, 4682e192b24SSimon Glass .cmd_func_offset = -1, 4692e192b24SSimon Glass .keyword_function = ðsw_vlan_learn_help_key_func, 4702e192b24SSimon Glass }, { 4712e192b24SSimon Glass .cmd_keyword = { 4722e192b24SSimon Glass ethsw_id_vlan, 4732e192b24SSimon Glass ethsw_id_fdb, 4742e192b24SSimon Glass ethsw_id_show, 4752e192b24SSimon Glass ethsw_id_key_end, 4762e192b24SSimon Glass }, 4772e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 4782e192b24SSimon Glass vlan_learn_show), 4792e192b24SSimon Glass .keyword_function = NULL, 4802e192b24SSimon Glass }, { 4812e192b24SSimon Glass .cmd_keyword = { 4822e192b24SSimon Glass ethsw_id_vlan, 4832e192b24SSimon Glass ethsw_id_fdb, 4842e192b24SSimon Glass ethsw_id_shared, 4852e192b24SSimon Glass ethsw_id_key_end, 4862e192b24SSimon Glass }, 4872e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 4882e192b24SSimon Glass vlan_learn_set), 4892e192b24SSimon Glass .keyword_function = NULL, 4902e192b24SSimon Glass }, { 4912e192b24SSimon Glass .cmd_keyword = { 4922e192b24SSimon Glass ethsw_id_vlan, 4932e192b24SSimon Glass ethsw_id_fdb, 4942e192b24SSimon Glass ethsw_id_private, 4952e192b24SSimon Glass ethsw_id_key_end, 4962e192b24SSimon Glass }, 4972e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 4982e192b24SSimon Glass vlan_learn_set), 4992e192b24SSimon Glass .keyword_function = NULL, 5002e192b24SSimon Glass }, { 5012e192b24SSimon Glass .cmd_keyword = { 5022e192b24SSimon Glass ethsw_id_ingress, 5032e192b24SSimon Glass ethsw_id_filtering, 5042e192b24SSimon Glass ethsw_id_key_end, 5052e192b24SSimon Glass }, 5062e192b24SSimon Glass .cmd_func_offset = -1, 5072e192b24SSimon Glass .keyword_function = ðsw_ingr_fltr_help_key_func, 5082e192b24SSimon Glass }, { 5092e192b24SSimon Glass .cmd_keyword = { 5102e192b24SSimon Glass ethsw_id_ingress, 5112e192b24SSimon Glass ethsw_id_filtering, 5122e192b24SSimon Glass ethsw_id_help, 5132e192b24SSimon Glass ethsw_id_key_end, 5142e192b24SSimon Glass }, 5152e192b24SSimon Glass .cmd_func_offset = -1, 5162e192b24SSimon Glass .keyword_function = ðsw_ingr_fltr_help_key_func, 5172e192b24SSimon Glass }, { 5182e192b24SSimon Glass .cmd_keyword = { 5192e192b24SSimon Glass ethsw_id_ingress, 5202e192b24SSimon Glass ethsw_id_filtering, 5212e192b24SSimon Glass ethsw_id_show, 5222e192b24SSimon Glass ethsw_id_key_end, 5232e192b24SSimon Glass }, 5242e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 5252e192b24SSimon Glass port_ingr_filt_show), 5262e192b24SSimon Glass .keyword_function = NULL, 5272e192b24SSimon Glass }, { 5282e192b24SSimon Glass .cmd_keyword = { 5292e192b24SSimon Glass ethsw_id_ingress, 5302e192b24SSimon Glass ethsw_id_filtering, 5312e192b24SSimon Glass ethsw_id_enable, 5322e192b24SSimon Glass ethsw_id_key_end, 5332e192b24SSimon Glass }, 5342e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 5352e192b24SSimon Glass port_ingr_filt_set), 5362e192b24SSimon Glass .keyword_function = NULL, 5372e192b24SSimon Glass }, { 5382e192b24SSimon Glass .cmd_keyword = { 5392e192b24SSimon Glass ethsw_id_ingress, 5402e192b24SSimon Glass ethsw_id_filtering, 5412e192b24SSimon Glass ethsw_id_disable, 5422e192b24SSimon Glass ethsw_id_key_end, 5432e192b24SSimon Glass }, 5442e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 5452e192b24SSimon Glass port_ingr_filt_set), 5462e192b24SSimon Glass .keyword_function = NULL, 54782d72a1bSTom Rini }, { 54882d72a1bSTom Rini .cmd_keyword = { 54982d72a1bSTom Rini ethsw_id_aggr, 55082d72a1bSTom Rini ethsw_id_key_end, 55182d72a1bSTom Rini }, 55282d72a1bSTom Rini .cmd_func_offset = -1, 55382d72a1bSTom Rini .keyword_function = ðsw_port_aggr_help_key_func, 55482d72a1bSTom Rini }, { 55582d72a1bSTom Rini .cmd_keyword = { 55682d72a1bSTom Rini ethsw_id_aggr, 55782d72a1bSTom Rini ethsw_id_help, 55882d72a1bSTom Rini ethsw_id_key_end, 55982d72a1bSTom Rini }, 56082d72a1bSTom Rini .cmd_func_offset = -1, 56182d72a1bSTom Rini .keyword_function = ðsw_port_aggr_help_key_func, 56282d72a1bSTom Rini }, { 56382d72a1bSTom Rini .cmd_keyword = { 56482d72a1bSTom Rini ethsw_id_aggr, 56582d72a1bSTom Rini ethsw_id_show, 56682d72a1bSTom Rini ethsw_id_key_end, 56782d72a1bSTom Rini }, 56882d72a1bSTom Rini .cmd_func_offset = offsetof(struct ethsw_command_func, 56982d72a1bSTom Rini port_aggr_show), 57082d72a1bSTom Rini .keyword_function = NULL, 57182d72a1bSTom Rini }, { 57282d72a1bSTom Rini .cmd_keyword = { 57382d72a1bSTom Rini ethsw_id_aggr, 57482d72a1bSTom Rini ethsw_id_aggr_no, 57582d72a1bSTom Rini ethsw_id_key_end, 57682d72a1bSTom Rini }, 57782d72a1bSTom Rini .cmd_func_offset = offsetof(struct ethsw_command_func, 57882d72a1bSTom Rini port_aggr_set), 57982d72a1bSTom Rini .keyword_function = NULL, 5802e192b24SSimon Glass }, 5812e192b24SSimon Glass }; 5822e192b24SSimon Glass 5832e192b24SSimon Glass struct keywords_optional { 5842e192b24SSimon Glass int cmd_keyword[ETHSW_MAX_CMD_PARAMS]; 5852e192b24SSimon Glass } cmd_opt_def[] = { 5862e192b24SSimon Glass { 5872e192b24SSimon Glass .cmd_keyword = { 5882e192b24SSimon Glass ethsw_id_port, 5892e192b24SSimon Glass ethsw_id_port_no, 5902e192b24SSimon Glass ethsw_id_key_end, 5912e192b24SSimon Glass }, 5922e192b24SSimon Glass }, { 5932e192b24SSimon Glass .cmd_keyword = { 5942e192b24SSimon Glass ethsw_id_vlan, 5952e192b24SSimon Glass ethsw_id_vlan_no, 5962e192b24SSimon Glass ethsw_id_key_end, 5972e192b24SSimon Glass }, 5982e192b24SSimon Glass }, { 5992e192b24SSimon Glass .cmd_keyword = { 6002e192b24SSimon Glass ethsw_id_port, 6012e192b24SSimon Glass ethsw_id_port_no, 6022e192b24SSimon Glass ethsw_id_vlan, 6032e192b24SSimon Glass ethsw_id_vlan_no, 6042e192b24SSimon Glass ethsw_id_key_end, 6052e192b24SSimon Glass }, 6062e192b24SSimon Glass }, 6072e192b24SSimon Glass }; 6082e192b24SSimon Glass 6092e192b24SSimon Glass static int keyword_match_gen(enum ethsw_keyword_id key_id, int argc, char 6102e192b24SSimon Glass *const argv[], int *argc_nr, 6112e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 6122e192b24SSimon Glass static int keyword_match_port(enum ethsw_keyword_id key_id, int argc, 6132e192b24SSimon Glass char *const argv[], int *argc_nr, 6142e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 6152e192b24SSimon Glass static int keyword_match_vlan(enum ethsw_keyword_id key_id, int argc, 6162e192b24SSimon Glass char *const argv[], int *argc_nr, 6172e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 6182e192b24SSimon Glass static int keyword_match_pvid(enum ethsw_keyword_id key_id, int argc, 6192e192b24SSimon Glass char *const argv[], int *argc_nr, 6202e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 6212e192b24SSimon Glass static int keyword_match_mac_addr(enum ethsw_keyword_id key_id, int argc, 6222e192b24SSimon Glass char *const argv[], int *argc_nr, 6232e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 62482d72a1bSTom Rini static int keyword_match_aggr(enum ethsw_keyword_id key_id, int argc, 62582d72a1bSTom Rini char *const argv[], int *argc_nr, 62682d72a1bSTom Rini struct ethsw_command_def *parsed_cmd); 6272e192b24SSimon Glass 6282e192b24SSimon Glass /* 6292e192b24SSimon Glass * Define properties for each keyword; 6302e192b24SSimon Glass * keep the order synced with enum ethsw_keyword_id 6312e192b24SSimon Glass */ 6322e192b24SSimon Glass struct keyword_def { 6332e192b24SSimon Glass const char *keyword_name; 6342e192b24SSimon Glass int (*match)(enum ethsw_keyword_id key_id, int argc, char *const argv[], 6352e192b24SSimon Glass int *argc_nr, struct ethsw_command_def *parsed_cmd); 6362e192b24SSimon Glass } keyword[] = { 6372e192b24SSimon Glass { 6382e192b24SSimon Glass .keyword_name = "help", 6392e192b24SSimon Glass .match = &keyword_match_gen, 6402e192b24SSimon Glass }, { 6412e192b24SSimon Glass .keyword_name = "show", 6422e192b24SSimon Glass .match = &keyword_match_gen, 6432e192b24SSimon Glass }, { 6442e192b24SSimon Glass .keyword_name = "port", 6452e192b24SSimon Glass .match = &keyword_match_port 6462e192b24SSimon Glass }, { 6472e192b24SSimon Glass .keyword_name = "enable", 6482e192b24SSimon Glass .match = &keyword_match_gen, 6492e192b24SSimon Glass }, { 6502e192b24SSimon Glass .keyword_name = "disable", 6512e192b24SSimon Glass .match = &keyword_match_gen, 6522e192b24SSimon Glass }, { 6532e192b24SSimon Glass .keyword_name = "statistics", 6542e192b24SSimon Glass .match = &keyword_match_gen, 6552e192b24SSimon Glass }, { 6562e192b24SSimon Glass .keyword_name = "clear", 6572e192b24SSimon Glass .match = &keyword_match_gen, 6582e192b24SSimon Glass }, { 6592e192b24SSimon Glass .keyword_name = "learning", 6602e192b24SSimon Glass .match = &keyword_match_gen, 6612e192b24SSimon Glass }, { 6622e192b24SSimon Glass .keyword_name = "auto", 6632e192b24SSimon Glass .match = &keyword_match_gen, 6642e192b24SSimon Glass }, { 6652e192b24SSimon Glass .keyword_name = "vlan", 6662e192b24SSimon Glass .match = &keyword_match_vlan, 6672e192b24SSimon Glass }, { 6682e192b24SSimon Glass .keyword_name = "fdb", 6692e192b24SSimon Glass .match = &keyword_match_gen, 6702e192b24SSimon Glass }, { 6712e192b24SSimon Glass .keyword_name = "add", 6722e192b24SSimon Glass .match = &keyword_match_mac_addr, 6732e192b24SSimon Glass }, { 6742e192b24SSimon Glass .keyword_name = "del", 6752e192b24SSimon Glass .match = &keyword_match_mac_addr, 6762e192b24SSimon Glass }, { 6772e192b24SSimon Glass .keyword_name = "flush", 6782e192b24SSimon Glass .match = &keyword_match_gen, 6792e192b24SSimon Glass }, { 6802e192b24SSimon Glass .keyword_name = "pvid", 6812e192b24SSimon Glass .match = &keyword_match_pvid, 6822e192b24SSimon Glass }, { 6832e192b24SSimon Glass .keyword_name = "untagged", 6842e192b24SSimon Glass .match = &keyword_match_gen, 6852e192b24SSimon Glass }, { 6862e192b24SSimon Glass .keyword_name = "all", 6872e192b24SSimon Glass .match = &keyword_match_gen, 6882e192b24SSimon Glass }, { 6892e192b24SSimon Glass .keyword_name = "none", 6902e192b24SSimon Glass .match = &keyword_match_gen, 6912e192b24SSimon Glass }, { 6922e192b24SSimon Glass .keyword_name = "egress", 6932e192b24SSimon Glass .match = &keyword_match_gen, 6942e192b24SSimon Glass }, { 6952e192b24SSimon Glass .keyword_name = "tag", 6962e192b24SSimon Glass .match = &keyword_match_gen, 6972e192b24SSimon Glass }, { 6982e192b24SSimon Glass .keyword_name = "classified", 6992e192b24SSimon Glass .match = &keyword_match_gen, 7002e192b24SSimon Glass }, { 7012e192b24SSimon Glass .keyword_name = "shared", 7022e192b24SSimon Glass .match = &keyword_match_gen, 7032e192b24SSimon Glass }, { 7042e192b24SSimon Glass .keyword_name = "private", 7052e192b24SSimon Glass .match = &keyword_match_gen, 7062e192b24SSimon Glass }, { 7072e192b24SSimon Glass .keyword_name = "ingress", 7082e192b24SSimon Glass .match = &keyword_match_gen, 7092e192b24SSimon Glass }, { 7102e192b24SSimon Glass .keyword_name = "filtering", 7112e192b24SSimon Glass .match = &keyword_match_gen, 71282d72a1bSTom Rini }, { 71382d72a1bSTom Rini .keyword_name = "aggr", 71482d72a1bSTom Rini .match = &keyword_match_aggr, 7152e192b24SSimon Glass }, 7162e192b24SSimon Glass }; 7172e192b24SSimon Glass 7182e192b24SSimon Glass /* 7192e192b24SSimon Glass * Function used by an Ethernet Switch driver to set the functions 7202e192b24SSimon Glass * that must be called by the parser when an ethsw command is given 7212e192b24SSimon Glass */ 7222e192b24SSimon Glass int ethsw_define_functions(const struct ethsw_command_func *cmd_func) 7232e192b24SSimon Glass { 7242e192b24SSimon Glass int i; 7252e192b24SSimon Glass void **aux_p; 7262e192b24SSimon Glass int (*cmd_func_aux)(struct ethsw_command_def *); 7272e192b24SSimon Glass 7282e192b24SSimon Glass if (!cmd_func->ethsw_name) 7292e192b24SSimon Glass return -EINVAL; 7302e192b24SSimon Glass 7312e192b24SSimon Glass ethsw_name = cmd_func->ethsw_name; 7322e192b24SSimon Glass 7332e192b24SSimon Glass for (i = 0; i < ARRAY_SIZE(ethsw_cmd_def); i++) { 7342e192b24SSimon Glass /* 7352e192b24SSimon Glass * get the pointer to the function send by the Ethernet Switch 7362e192b24SSimon Glass * driver that corresponds to the proper ethsw command 7372e192b24SSimon Glass */ 7382e192b24SSimon Glass if (ethsw_cmd_def[i].keyword_function) 7392e192b24SSimon Glass continue; 7402e192b24SSimon Glass 7412e192b24SSimon Glass aux_p = (void *)cmd_func + ethsw_cmd_def[i].cmd_func_offset; 7422e192b24SSimon Glass 7432e192b24SSimon Glass cmd_func_aux = (int (*)(struct ethsw_command_def *)) *aux_p; 7442e192b24SSimon Glass ethsw_cmd_def[i].keyword_function = cmd_func_aux; 7452e192b24SSimon Glass } 7462e192b24SSimon Glass 7472e192b24SSimon Glass return 0; 7482e192b24SSimon Glass } 7492e192b24SSimon Glass 7502e192b24SSimon Glass /* Generic function used to match a keyword only by a string */ 7512e192b24SSimon Glass static int keyword_match_gen(enum ethsw_keyword_id key_id, int argc, 7522e192b24SSimon Glass char *const argv[], int *argc_nr, 7532e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 7542e192b24SSimon Glass { 7552e192b24SSimon Glass if (strcmp(argv[*argc_nr], keyword[key_id].keyword_name) == 0) { 7562e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = key_id; 7572e192b24SSimon Glass 7582e192b24SSimon Glass return 1; 7592e192b24SSimon Glass } 7602e192b24SSimon Glass return 0; 7612e192b24SSimon Glass } 7622e192b24SSimon Glass 7632e192b24SSimon Glass /* Function used to match the command's port */ 7642e192b24SSimon Glass static int keyword_match_port(enum ethsw_keyword_id key_id, int argc, 7652e192b24SSimon Glass char *const argv[], int *argc_nr, 7662e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 7672e192b24SSimon Glass { 7682e192b24SSimon Glass unsigned long val; 7692e192b24SSimon Glass 7702e192b24SSimon Glass if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 7712e192b24SSimon Glass return 0; 7722e192b24SSimon Glass 7732e192b24SSimon Glass if (*argc_nr + 1 >= argc) 7742e192b24SSimon Glass return 0; 7752e192b24SSimon Glass 7762e192b24SSimon Glass if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) { 7772e192b24SSimon Glass parsed_cmd->port = val; 7782e192b24SSimon Glass (*argc_nr)++; 7792e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_port_no; 7802e192b24SSimon Glass return 1; 7812e192b24SSimon Glass } 7822e192b24SSimon Glass 7832e192b24SSimon Glass return 0; 7842e192b24SSimon Glass } 7852e192b24SSimon Glass 7862e192b24SSimon Glass /* Function used to match the command's vlan */ 7872e192b24SSimon Glass static int keyword_match_vlan(enum ethsw_keyword_id key_id, int argc, 7882e192b24SSimon Glass char *const argv[], int *argc_nr, 7892e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 7902e192b24SSimon Glass { 7912e192b24SSimon Glass unsigned long val; 7922e192b24SSimon Glass int aux; 7932e192b24SSimon Glass 7942e192b24SSimon Glass if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 7952e192b24SSimon Glass return 0; 7962e192b24SSimon Glass 7972e192b24SSimon Glass if (*argc_nr + 1 >= argc) 7982e192b24SSimon Glass return 0; 7992e192b24SSimon Glass 8002e192b24SSimon Glass if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) { 8012e192b24SSimon Glass parsed_cmd->vid = val; 8022e192b24SSimon Glass (*argc_nr)++; 8032e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_vlan_no; 8042e192b24SSimon Glass return 1; 8052e192b24SSimon Glass } 8062e192b24SSimon Glass 8072e192b24SSimon Glass aux = *argc_nr + 1; 8082e192b24SSimon Glass 8092e192b24SSimon Glass if (keyword_match_gen(ethsw_id_add, argc, argv, &aux, parsed_cmd)) 8102e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_add; 8112e192b24SSimon Glass else if (keyword_match_gen(ethsw_id_del, argc, argv, &aux, parsed_cmd)) 8122e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_del; 8132e192b24SSimon Glass else 8142e192b24SSimon Glass return 0; 8152e192b24SSimon Glass 8162e192b24SSimon Glass if (*argc_nr + 2 >= argc) 8172e192b24SSimon Glass return 0; 8182e192b24SSimon Glass 8192e192b24SSimon Glass if (strict_strtoul(argv[*argc_nr + 2], 10, &val) != -EINVAL) { 8202e192b24SSimon Glass parsed_cmd->vid = val; 8212e192b24SSimon Glass (*argc_nr) += 2; 8222e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_add_del_no; 8232e192b24SSimon Glass return 1; 8242e192b24SSimon Glass } 8252e192b24SSimon Glass 8262e192b24SSimon Glass return 0; 8272e192b24SSimon Glass } 8282e192b24SSimon Glass 8292e192b24SSimon Glass /* Function used to match the command's pvid */ 8302e192b24SSimon Glass static int keyword_match_pvid(enum ethsw_keyword_id key_id, int argc, 8312e192b24SSimon Glass char *const argv[], int *argc_nr, 8322e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 8332e192b24SSimon Glass { 8342e192b24SSimon Glass unsigned long val; 8352e192b24SSimon Glass 8362e192b24SSimon Glass if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 8372e192b24SSimon Glass return 0; 8382e192b24SSimon Glass 8392e192b24SSimon Glass if (*argc_nr + 1 >= argc) 8402e192b24SSimon Glass return 1; 8412e192b24SSimon Glass 8422e192b24SSimon Glass if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) { 8432e192b24SSimon Glass parsed_cmd->vid = val; 8442e192b24SSimon Glass (*argc_nr)++; 8452e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_pvid_no; 8462e192b24SSimon Glass } 8472e192b24SSimon Glass 8482e192b24SSimon Glass return 1; 8492e192b24SSimon Glass } 8502e192b24SSimon Glass 8512e192b24SSimon Glass /* Function used to match the command's MAC address */ 8522e192b24SSimon Glass static int keyword_match_mac_addr(enum ethsw_keyword_id key_id, int argc, 8532e192b24SSimon Glass char *const argv[], int *argc_nr, 8542e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 8552e192b24SSimon Glass { 8562e192b24SSimon Glass if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 8572e192b24SSimon Glass return 0; 8582e192b24SSimon Glass 8592e192b24SSimon Glass if ((*argc_nr + 1 >= argc) || 8602e192b24SSimon Glass !is_broadcast_ethaddr(parsed_cmd->ethaddr)) 8612e192b24SSimon Glass return 1; 8622e192b24SSimon Glass 8632e192b24SSimon Glass if (eth_validate_ethaddr_str(argv[*argc_nr + 1])) { 8642e192b24SSimon Glass printf("Invalid MAC address: %s\n", argv[*argc_nr + 1]); 8652e192b24SSimon Glass return 0; 8662e192b24SSimon Glass } 8672e192b24SSimon Glass 8682e192b24SSimon Glass eth_parse_enetaddr(argv[*argc_nr + 1], parsed_cmd->ethaddr); 8692e192b24SSimon Glass 8702e192b24SSimon Glass if (is_broadcast_ethaddr(parsed_cmd->ethaddr)) { 8712e192b24SSimon Glass memset(parsed_cmd->ethaddr, 0xFF, sizeof(parsed_cmd->ethaddr)); 8722e192b24SSimon Glass return 0; 8732e192b24SSimon Glass } 8742e192b24SSimon Glass 8752e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_add_del_mac; 8762e192b24SSimon Glass 8772e192b24SSimon Glass return 1; 8782e192b24SSimon Glass } 8792e192b24SSimon Glass 88082d72a1bSTom Rini /* Function used to match the command's aggregation number */ 88182d72a1bSTom Rini static int keyword_match_aggr(enum ethsw_keyword_id key_id, int argc, 88282d72a1bSTom Rini char *const argv[], int *argc_nr, 88382d72a1bSTom Rini struct ethsw_command_def *parsed_cmd) 88482d72a1bSTom Rini { 88582d72a1bSTom Rini unsigned long val; 88682d72a1bSTom Rini 88782d72a1bSTom Rini if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 88882d72a1bSTom Rini return 0; 88982d72a1bSTom Rini 89082d72a1bSTom Rini if (*argc_nr + 1 >= argc) 89182d72a1bSTom Rini return 1; 89282d72a1bSTom Rini 89382d72a1bSTom Rini if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) { 89482d72a1bSTom Rini parsed_cmd->aggr_grp = val; 89582d72a1bSTom Rini (*argc_nr)++; 89682d72a1bSTom Rini parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_aggr_no; 89782d72a1bSTom Rini } 89882d72a1bSTom Rini 89982d72a1bSTom Rini return 1; 90082d72a1bSTom Rini } 90182d72a1bSTom Rini 9022e192b24SSimon Glass /* Finds optional keywords and modifies *argc_va to skip them */ 9032e192b24SSimon Glass static void cmd_keywords_opt_check(const struct ethsw_command_def *parsed_cmd, 9042e192b24SSimon Glass int *argc_val) 9052e192b24SSimon Glass { 9062e192b24SSimon Glass int i; 9072e192b24SSimon Glass int keyw_opt_matched; 9082e192b24SSimon Glass int argc_val_max; 9092e192b24SSimon Glass int const *cmd_keyw_p; 9102e192b24SSimon Glass int const *cmd_keyw_opt_p; 9112e192b24SSimon Glass 9122e192b24SSimon Glass /* remember the best match */ 9132e192b24SSimon Glass argc_val_max = *argc_val; 9142e192b24SSimon Glass 9152e192b24SSimon Glass /* 9162e192b24SSimon Glass * check if our command's optional keywords match the optional 9172e192b24SSimon Glass * keywords of an available command 9182e192b24SSimon Glass */ 91931417f0eSYork Sun for (i = 0; i < ARRAY_SIZE(cmd_opt_def); i++) { 9202e192b24SSimon Glass keyw_opt_matched = 0; 9212e192b24SSimon Glass cmd_keyw_p = &parsed_cmd->cmd_to_keywords[keyw_opt_matched]; 9222e192b24SSimon Glass cmd_keyw_opt_p = &cmd_opt_def[i].cmd_keyword[keyw_opt_matched]; 9232e192b24SSimon Glass 9242e192b24SSimon Glass /* 9252e192b24SSimon Glass * increase the number of keywords that 9262e192b24SSimon Glass * matched with a command 9272e192b24SSimon Glass */ 9282e192b24SSimon Glass while (keyw_opt_matched + *argc_val < 9292e192b24SSimon Glass parsed_cmd->cmd_keywords_nr && 9302e192b24SSimon Glass *cmd_keyw_opt_p != ethsw_id_key_end && 9312e192b24SSimon Glass *(cmd_keyw_p + *argc_val) == *cmd_keyw_opt_p) { 9322e192b24SSimon Glass keyw_opt_matched++; 9332e192b24SSimon Glass cmd_keyw_p++; 9342e192b24SSimon Glass cmd_keyw_opt_p++; 9352e192b24SSimon Glass } 9362e192b24SSimon Glass 9372e192b24SSimon Glass /* 9382e192b24SSimon Glass * if all our optional command's keywords perfectly match an 9392e192b24SSimon Glass * optional pattern, then we can move to the next defined 9402e192b24SSimon Glass * keywords in our command; remember the one that matched the 9412e192b24SSimon Glass * greatest number of keywords 9422e192b24SSimon Glass */ 9432e192b24SSimon Glass if (keyw_opt_matched + *argc_val <= 9442e192b24SSimon Glass parsed_cmd->cmd_keywords_nr && 9452e192b24SSimon Glass *cmd_keyw_opt_p == ethsw_id_key_end && 9462e192b24SSimon Glass *argc_val + keyw_opt_matched > argc_val_max) 9472e192b24SSimon Glass argc_val_max = *argc_val + keyw_opt_matched; 9482e192b24SSimon Glass } 9492e192b24SSimon Glass 9502e192b24SSimon Glass *argc_val = argc_val_max; 9512e192b24SSimon Glass } 9522e192b24SSimon Glass 9532e192b24SSimon Glass /* 9542e192b24SSimon Glass * Finds the function to call based on keywords and 9552e192b24SSimon Glass * modifies *argc_va to skip them 9562e192b24SSimon Glass */ 9572e192b24SSimon Glass static void cmd_keywords_check(struct ethsw_command_def *parsed_cmd, 9582e192b24SSimon Glass int *argc_val) 9592e192b24SSimon Glass { 9602e192b24SSimon Glass int i; 9612e192b24SSimon Glass int keyw_matched; 9622e192b24SSimon Glass int *cmd_keyw_p; 9632e192b24SSimon Glass int *cmd_keyw_def_p; 9642e192b24SSimon Glass 9652e192b24SSimon Glass /* 9662e192b24SSimon Glass * check if our command's keywords match the 9672e192b24SSimon Glass * keywords of an available command 9682e192b24SSimon Glass */ 9692e192b24SSimon Glass for (i = 0; i < ARRAY_SIZE(ethsw_cmd_def); i++) { 9702e192b24SSimon Glass keyw_matched = 0; 9712e192b24SSimon Glass cmd_keyw_p = &parsed_cmd->cmd_to_keywords[keyw_matched]; 9722e192b24SSimon Glass cmd_keyw_def_p = ðsw_cmd_def[i].cmd_keyword[keyw_matched]; 9732e192b24SSimon Glass 9742e192b24SSimon Glass /* 9752e192b24SSimon Glass * increase the number of keywords that 9762e192b24SSimon Glass * matched with a command 9772e192b24SSimon Glass */ 9782e192b24SSimon Glass while (keyw_matched + *argc_val < parsed_cmd->cmd_keywords_nr && 9792e192b24SSimon Glass *cmd_keyw_def_p != ethsw_id_key_end && 9802e192b24SSimon Glass *(cmd_keyw_p + *argc_val) == *cmd_keyw_def_p) { 9812e192b24SSimon Glass keyw_matched++; 9822e192b24SSimon Glass cmd_keyw_p++; 9832e192b24SSimon Glass cmd_keyw_def_p++; 9842e192b24SSimon Glass } 9852e192b24SSimon Glass 9862e192b24SSimon Glass /* 9872e192b24SSimon Glass * if all our command's keywords perfectly match an 9882e192b24SSimon Glass * available command, then we get the function we need to call 9892e192b24SSimon Glass * to configure the Ethernet Switch 9902e192b24SSimon Glass */ 9912e192b24SSimon Glass if (keyw_matched && keyw_matched + *argc_val == 9922e192b24SSimon Glass parsed_cmd->cmd_keywords_nr && 9932e192b24SSimon Glass *cmd_keyw_def_p == ethsw_id_key_end) { 9942e192b24SSimon Glass *argc_val += keyw_matched; 9952e192b24SSimon Glass parsed_cmd->cmd_function = 9962e192b24SSimon Glass ethsw_cmd_def[i].keyword_function; 9972e192b24SSimon Glass return; 9982e192b24SSimon Glass } 9992e192b24SSimon Glass } 10002e192b24SSimon Glass } 10012e192b24SSimon Glass 10022e192b24SSimon Glass /* find all the keywords in the command */ 10032e192b24SSimon Glass static int keywords_find(int argc, char * const argv[], 10042e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 10052e192b24SSimon Glass { 10062e192b24SSimon Glass int i; 10072e192b24SSimon Glass int j; 10082e192b24SSimon Glass int argc_val; 10092e192b24SSimon Glass int rc = CMD_RET_SUCCESS; 10102e192b24SSimon Glass 10112e192b24SSimon Glass for (i = 1; i < argc; i++) { 10122e192b24SSimon Glass for (j = 0; j < ethsw_id_count; j++) { 10132e192b24SSimon Glass if (keyword[j].match(j, argc, argv, &i, parsed_cmd)) 10142e192b24SSimon Glass break; 10152e192b24SSimon Glass } 10162e192b24SSimon Glass } 10172e192b24SSimon Glass 10182e192b24SSimon Glass /* if there is no keyword match for a word, the command is invalid */ 10192e192b24SSimon Glass for (i = 1; i < argc; i++) 10202e192b24SSimon Glass if (parsed_cmd->cmd_to_keywords[i] == ethsw_id_key_end) 10212e192b24SSimon Glass rc = CMD_RET_USAGE; 10222e192b24SSimon Glass 10232e192b24SSimon Glass parsed_cmd->cmd_keywords_nr = argc; 10242e192b24SSimon Glass argc_val = 1; 10252e192b24SSimon Glass 10262e192b24SSimon Glass /* get optional parameters first */ 10272e192b24SSimon Glass cmd_keywords_opt_check(parsed_cmd, &argc_val); 10282e192b24SSimon Glass 10292e192b24SSimon Glass if (argc_val == parsed_cmd->cmd_keywords_nr) 10302e192b24SSimon Glass return CMD_RET_USAGE; 10312e192b24SSimon Glass 10322e192b24SSimon Glass /* 10332e192b24SSimon Glass * check the keywords and if a match is found, 10342e192b24SSimon Glass * get the function to call 10352e192b24SSimon Glass */ 10362e192b24SSimon Glass cmd_keywords_check(parsed_cmd, &argc_val); 10372e192b24SSimon Glass 10382e192b24SSimon Glass /* error if not all commands' parameters were matched */ 10392e192b24SSimon Glass if (argc_val == parsed_cmd->cmd_keywords_nr) { 10402e192b24SSimon Glass if (!parsed_cmd->cmd_function) { 10412e192b24SSimon Glass printf("Command not available for: %s\n", ethsw_name); 10422e192b24SSimon Glass rc = CMD_RET_FAILURE; 10432e192b24SSimon Glass } 10442e192b24SSimon Glass } else { 10452e192b24SSimon Glass rc = CMD_RET_USAGE; 10462e192b24SSimon Glass } 10472e192b24SSimon Glass 10482e192b24SSimon Glass return rc; 10492e192b24SSimon Glass } 10502e192b24SSimon Glass 10512e192b24SSimon Glass static void command_def_init(struct ethsw_command_def *parsed_cmd) 10522e192b24SSimon Glass { 10532e192b24SSimon Glass int i; 10542e192b24SSimon Glass 10552e192b24SSimon Glass for (i = 0; i < ETHSW_MAX_CMD_PARAMS; i++) 10562e192b24SSimon Glass parsed_cmd->cmd_to_keywords[i] = ethsw_id_key_end; 10572e192b24SSimon Glass 10582e192b24SSimon Glass parsed_cmd->port = ETHSW_CMD_PORT_ALL; 10592e192b24SSimon Glass parsed_cmd->vid = ETHSW_CMD_VLAN_ALL; 106082d72a1bSTom Rini parsed_cmd->aggr_grp = ETHSW_CMD_AGGR_GRP_NONE; 10612e192b24SSimon Glass parsed_cmd->cmd_function = NULL; 10622e192b24SSimon Glass 10632e192b24SSimon Glass /* We initialize the MAC address with the Broadcast address */ 10642e192b24SSimon Glass memset(parsed_cmd->ethaddr, 0xff, sizeof(parsed_cmd->ethaddr)); 10652e192b24SSimon Glass } 10662e192b24SSimon Glass 10672e192b24SSimon Glass /* function to interpret commands starting with "ethsw " */ 10682e192b24SSimon Glass static int do_ethsw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 10692e192b24SSimon Glass { 10702e192b24SSimon Glass struct ethsw_command_def parsed_cmd; 10712e192b24SSimon Glass int rc = CMD_RET_SUCCESS; 10722e192b24SSimon Glass 10732e192b24SSimon Glass if (argc == 1 || argc >= ETHSW_MAX_CMD_PARAMS) 10742e192b24SSimon Glass return CMD_RET_USAGE; 10752e192b24SSimon Glass 10762e192b24SSimon Glass command_def_init(&parsed_cmd); 10772e192b24SSimon Glass 10782e192b24SSimon Glass rc = keywords_find(argc, argv, &parsed_cmd); 10792e192b24SSimon Glass 10802e192b24SSimon Glass if (rc == CMD_RET_SUCCESS) 10812e192b24SSimon Glass rc = parsed_cmd.cmd_function(&parsed_cmd); 10822e192b24SSimon Glass 10832e192b24SSimon Glass return rc; 10842e192b24SSimon Glass } 10852e192b24SSimon Glass 10862e192b24SSimon Glass #define ETHSW_PORT_CONF_HELP "[port <port_no>] { enable | disable | show } " \ 108782d72a1bSTom Rini "- enable/disable a port; show a port's configuration" 10882e192b24SSimon Glass 10892e192b24SSimon Glass U_BOOT_CMD(ethsw, ETHSW_MAX_CMD_PARAMS, 0, do_ethsw, 10902e192b24SSimon Glass "Ethernet l2 switch commands", 10912e192b24SSimon Glass ETHSW_PORT_CONF_HELP"\n" 10922e192b24SSimon Glass ETHSW_PORT_STATS_HELP"\n" 10932e192b24SSimon Glass ETHSW_LEARN_HELP"\n" 10942e192b24SSimon Glass ETHSW_FDB_HELP"\n" 10952e192b24SSimon Glass ETHSW_PVID_HELP"\n" 10962e192b24SSimon Glass ETHSW_VLAN_HELP"\n" 10972e192b24SSimon Glass ETHSW_PORT_UNTAG_HELP"\n" 10982e192b24SSimon Glass ETHSW_EGR_VLAN_TAG_HELP"\n" 10992e192b24SSimon Glass ETHSW_VLAN_FDB_HELP"\n" 11002e192b24SSimon Glass ETHSW_PORT_INGR_FLTR_HELP"\n" 110182d72a1bSTom Rini ETHSW_PORT_AGGR_HELP"\n" 11022e192b24SSimon Glass ); 1103