Merge "[qca-ssdk-shell]: support loopback port mib for cypress."
diff --git a/include/api/api_desc.h b/include/api/api_desc.h
index 707f940..6980e37 100755
--- a/include/api/api_desc.h
+++ b/include/api/api_desc.h
@@ -503,6 +503,18 @@
     SW_PARAM_DEF(SW_API_PT_SOURCE_FILTER_CONFIG_SET, SW_SRC_FILTER_CONFIG, \
         sizeof(fal_src_filter_config_t), SW_PARAM_PTR|SW_PARAM_IN, "srcfilter config"),
 
+#define SW_API_PT_SWITCH_PORT_LOOPBACK_SET_DESC \
+    SW_PARAM_DEF(SW_API_PT_SWITCH_PORT_LOOPBACK_SET, SW_UINT32, 4, SW_PARAM_IN, "Dev ID"), \
+    SW_PARAM_DEF(SW_API_PT_SWITCH_PORT_LOOPBACK_SET, SW_UINT32, 4, SW_PARAM_IN, "Port ID"), \
+    SW_PARAM_DEF(SW_API_PT_SWITCH_PORT_LOOPBACK_SET, SW_PORT_LOOPBACK_CONFIG, \
+        sizeof(fal_loopback_config_t), SW_PARAM_PTR|SW_PARAM_IN, "LOOPBACK"),
+
+#define SW_API_PT_SWITCH_PORT_LOOPBACK_GET_DESC \
+    SW_PARAM_DEF(SW_API_PT_SWITCH_PORT_LOOPBACK_GET, SW_UINT32, 4, SW_PARAM_IN, "Dev ID"), \
+    SW_PARAM_DEF(SW_API_PT_SWITCH_PORT_LOOPBACK_GET, SW_UINT32, 4, SW_PARAM_IN, "Port ID"), \
+    SW_PARAM_DEF(SW_API_PT_SWITCH_PORT_LOOPBACK_GET, SW_PORT_LOOPBACK_CONFIG,\
+        sizeof(fal_loopback_config_t), SW_PARAM_PTR|SW_PARAM_OUT, "LOOPBACK"),
+
 #define SW_API_VLAN_ADD_DESC \
     SW_PARAM_DEF(SW_API_VLAN_ADD, SW_UINT32, 4, SW_PARAM_IN, "Dev ID"), \
     SW_PARAM_DEF(SW_API_VLAN_ADD, SW_UINT32, 4, SW_PARAM_IN, "Vlan Id"),
diff --git a/include/api/sw_api.h b/include/api/sw_api.h
index e1dc09c..e2a5bf1 100755
--- a/include/api/sw_api.h
+++ b/include/api/sw_api.h
@@ -230,6 +230,7 @@
 	SW_RESOURCE_SCHE,
 	SW_PORT_EEE_CONFIG,
 	SW_SRC_FILTER_CONFIG,
+	SW_PORT_LOOPBACK_CONFIG,
 } sw_data_type_e;
 
     typedef struct
diff --git a/include/api/sw_ioctl.h b/include/api/sw_ioctl.h
index 69d0a33..1083984 100755
--- a/include/api/sw_ioctl.h
+++ b/include/api/sw_ioctl.h
@@ -123,6 +123,8 @@
 #define SW_API_PT_PROMISC_MODE_GET   (78  + SW_API_PORT_OFFSET)
 #define SW_API_PT_INTERFACE_EEE_CFG_SET  (79 + SW_API_PORT_OFFSET)
 #define SW_API_PT_INTERFACE_EEE_CFG_GET  (80 + SW_API_PORT_OFFSET)
+#define SW_API_PT_SWITCH_PORT_LOOPBACK_SET  (81 + SW_API_PORT_OFFSET)
+#define SW_API_PT_SWITCH_PORT_LOOPBACK_GET  (82 + SW_API_PORT_OFFSET)
 
     /*vlan*/
 #define SW_API_VLAN_OFFSET         130
diff --git a/include/fal/fal_api.h b/include/fal/fal_api.h
index 9cc0d12..59c59c1 100755
--- a/include/fal/fal_api.h
+++ b/include/fal/fal_api.h
@@ -125,7 +125,9 @@
     SW_API_DEF(SW_API_PT_INTERFACE_EEE_CFG_SET, fal_port_interface_eee_cfg_set),  \
     SW_API_DEF(SW_API_PT_INTERFACE_EEE_CFG_GET, fal_port_interface_eee_cfg_get),  \
     SW_API_DEF(SW_API_PT_SOURCE_FILTER_CONFIG_GET, fal_port_source_filter_config_get),\
-    SW_API_DEF(SW_API_PT_SOURCE_FILTER_CONFIG_SET, fal_port_source_filter_config_set),
+    SW_API_DEF(SW_API_PT_SOURCE_FILTER_CONFIG_SET, fal_port_source_filter_config_set), \
+    SW_API_DEF(SW_API_PT_SWITCH_PORT_LOOPBACK_SET, fal_switch_port_loopback_set),  \
+    SW_API_DEF(SW_API_PT_SWITCH_PORT_LOOPBACK_GET, fal_switch_port_loopback_get),
 /*qca808x_start*/\
 /*end of PORTCONTROL_API*/
 #define PORTCONTROL_API_PARAM \
@@ -230,7 +232,9 @@
     SW_API_DESC(SW_API_PT_INTERFACE_EEE_CFG_SET)  \
     SW_API_DESC(SW_API_PT_INTERFACE_EEE_CFG_GET)  \
     SW_API_DESC(SW_API_PT_SOURCE_FILTER_CONFIG_GET) \
-    SW_API_DESC(SW_API_PT_SOURCE_FILTER_CONFIG_SET)
+    SW_API_DESC(SW_API_PT_SOURCE_FILTER_CONFIG_SET)  \
+    SW_API_DESC(SW_API_PT_SWITCH_PORT_LOOPBACK_SET)  \
+    SW_API_DESC(SW_API_PT_SWITCH_PORT_LOOPBACK_GET)
 /*qca808x_start*/\
 /*end of PORTCONTROL_API_PARAM*/
 /*qca808x_end*/
diff --git a/include/fal/fal_port_ctrl.h b/include/fal/fal_port_ctrl.h
index aad0dd2..2b63059 100755
--- a/include/fal/fal_port_ctrl.h
+++ b/include/fal/fal_port_ctrl.h
@@ -393,6 +393,12 @@
 		fal_src_filter_mode_t	src_filter_mode;
 	} fal_src_filter_config_t;
 
+	typedef struct {
+		a_bool_t enable;
+		a_bool_t crc_stripped;
+		a_uint32_t loopback_rate; /*Mpps*/
+	}fal_loopback_config_t;
+
 	sw_error_t
 	fal_port_max_frame_size_set(a_uint32_t dev_id, fal_port_t port_id,
 			a_uint32_t max_frame);
@@ -751,6 +757,15 @@
 sw_error_t
 fal_port_source_filter_config_set(a_uint32_t dev_id,
 	fal_port_t port_id, fal_src_filter_config_t *src_filter_config);
+
+sw_error_t
+fal_switch_port_loopback_get(a_uint32_t dev_id, fal_port_t port_id,
+	fal_loopback_config_t *loopback_cfg);
+
+sw_error_t
+fal_switch_port_loopback_set(a_uint32_t dev_id, fal_port_t port_id,
+	fal_loopback_config_t *loopback_cfg);
+
 /*qca808x_start*/
 #ifdef __cplusplus
 }
diff --git a/include/shell/shell_io.h b/include/shell/shell_io.h
index be6a93b..d086c3f 100755
--- a/include/shell/shell_io.h
+++ b/include/shell/shell_io.h
@@ -647,6 +647,12 @@
 cmd_data_print_src_filter_config(a_uint8_t * param_name, a_uint32_t * buf, a_uint32_t size);
 
 sw_error_t
+cmd_data_check_switch_port_loopback_config(char *cmd_str, void * val,
+	a_uint32_t size);
+void
+cmd_data_print_switch_port_loopback_config(a_uint8_t * param_name,
+	a_uint32_t * buf, a_uint32_t size);
+sw_error_t
 cmd_data_check_newadr_lrn(char *cmd_str, void * val, a_uint32_t size);
 
 void
diff --git a/src/fal_uk/fal_port_ctrl.c b/src/fal_uk/fal_port_ctrl.c
index ae747ed..f031a87 100755
--- a/src/fal_uk/fal_port_ctrl.c
+++ b/src/fal_uk/fal_port_ctrl.c
@@ -929,3 +929,28 @@
 
 	return rv;
 }
+
+sw_error_t
+fal_switch_port_loopback_set(a_uint32_t dev_id, fal_port_t port_id,
+	fal_loopback_config_t *loopback_cfg)
+{
+	sw_error_t rv;
+
+	rv = sw_uk_exec(SW_API_PT_SWITCH_PORT_LOOPBACK_SET, dev_id,
+			port_id, loopback_cfg);
+
+	return rv;
+}
+sw_error_t
+fal_switch_port_loopback_get(a_uint32_t dev_id, fal_port_t port_id,
+	fal_loopback_config_t *loopback_cfg)
+
+{
+	sw_error_t rv;
+
+	rv = sw_uk_exec(SW_API_PT_SWITCH_PORT_LOOPBACK_GET, dev_id, port_id,
+			loopback_cfg);
+
+	return rv;
+}
+
diff --git a/src/shell/shell_config.c b/src/shell/shell_config.c
index b0ba5a8..741fc19 100755
--- a/src/shell/shell_config.c
+++ b/src/shell/shell_config.c
@@ -210,6 +210,10 @@
                 SW_API_PT_SOURCE_FILTER_CONFIG_SET, NULL},
             {"srcfiltercfg", "get", "get port source filter configure", "<port_id>",
                 SW_API_PT_SOURCE_FILTER_CONFIG_GET, NULL},
+            {"switchportloopback", "set", "set switch port loopback", "<port_id>",
+                SW_API_PT_SWITCH_PORT_LOOPBACK_SET, NULL},
+            {"switchportloopback", "get", "get switch port loopback", "<port_id>",
+                SW_API_PT_SWITCH_PORT_LOOPBACK_GET, NULL},
 /*qca808x_start*/
             {NULL, NULL, NULL, NULL, (int)NULL, NULL},/*end of desc*/
         },
diff --git a/src/shell/shell_io.c b/src/shell/shell_io.c
index 6fe2dcd..34a56bb 100755
--- a/src/shell/shell_io.c
+++ b/src/shell/shell_io.c
@@ -246,10 +246,11 @@
 	SW_TYPE_DEF(SW_CROSSOVER_MODE, cmd_data_check_crossover_mode, cmd_data_print_crossover_mode),
     SW_TYPE_DEF(SW_CROSSOVER_STATUS, cmd_data_check_crossover_status, cmd_data_print_crossover_status),
 /*qca808x_end*/
-	SW_TYPE_DEF(SW_PORT_EEE_CONFIG, cmd_data_check_port_eee_config, cmd_data_print_port_eee_config),
+    SW_TYPE_DEF(SW_PORT_EEE_CONFIG, cmd_data_check_port_eee_config, cmd_data_print_port_eee_config),
     SW_TYPE_DEF(SW_PREFER_MEDIUM, cmd_data_check_prefer_medium, cmd_data_print_prefer_medium),
     SW_TYPE_DEF(SW_FIBER_MODE, cmd_data_check_fiber_mode, cmd_data_print_fiber_mode),
     SW_TYPE_DEF(SW_SRC_FILTER_CONFIG, cmd_data_check_src_filter_config, cmd_data_print_src_filter_config),
+    SW_TYPE_DEF(SW_PORT_LOOPBACK_CONFIG, cmd_data_check_switch_port_loopback_config, cmd_data_print_switch_port_loopback_config),
 /*qca808x_start*/
     SW_TYPE_DEF(SW_INTERFACE_MODE, cmd_data_check_interface_mode, cmd_data_print_interface_mode),
     SW_TYPE_DEF(SW_COUNTER_INFO, NULL, cmd_data_print_counter_info),
@@ -9152,6 +9153,123 @@
 
     return;
 }
+
+sw_error_t
+cmd_data_check_switch_port_loopback_config(char *cmd_str, void * val,
+	a_uint32_t size)
+{
+    char *cmd;
+    sw_error_t rv;
+    fal_loopback_config_t cfg;
+
+    aos_mem_zero(&cfg, sizeof (fal_loopback_config_t));
+
+    do
+    {
+        cmd = get_sub_cmd("loopback_enable", "no");
+        SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            dprintf("usage: <yes/no/y/n>\n");
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_confirm(cmd, A_FALSE, &(cfg.enable),
+                                        sizeof (a_bool_t));
+            if (SW_OK != rv)
+                dprintf("usage: <yes/no/y/n>\n");
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    do
+    {
+        cmd = get_sub_cmd("crc_stripped_enable", "no");
+        SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            dprintf("usage: <yes/no/y/n>\n");
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_confirm(cmd, A_FALSE, &(cfg.crc_stripped),
+                                        sizeof (a_bool_t));
+            if (SW_OK != rv)
+                dprintf("usage: <yes/no/y/n>\n");
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    do
+    {
+        cmd = get_sub_cmd("loopback_rate", "1-0x12c");
+		SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            dprintf("usage: integer [unit is Mpps]\n");
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_uint32(cmd, &(cfg.loopback_rate), sizeof (a_uint32_t));
+            if (SW_OK != rv)
+                dprintf("usage: integer [unit is Mpps]\n");
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    *(fal_loopback_config_t *)val = cfg;
+    return SW_OK;
+}
+void
+cmd_data_print_switch_port_loopback_config(a_uint8_t * param_name,
+	a_uint32_t * buf, a_uint32_t size)
+{
+    fal_loopback_config_t *cfg;
+
+    cfg = (fal_loopback_config_t *) buf;
+
+    if (A_TRUE == cfg->enable)
+    {
+        dprintf("\n[loopback_enable]:yes  ");
+    }
+    else
+    {
+        dprintf("\n[loopback_enable]:no  ");
+    }
+    if (A_TRUE == cfg->crc_stripped)
+    {
+        dprintf("\n[crc_stripped_enable]:yes  ");
+    }
+    else
+    {
+        dprintf("\n[crc_stripped_enable]:no  ");
+    }
+
+    dprintf("\n[loopback_rate]:%d[Mpps]", cfg->loopback_rate);
+
+    return;
+}
+
 /*qca808x_start*/
 void
 cmd_data_print_cable_status(a_uint8_t * param_name, a_uint32_t * buf, a_uint32_t size)