mirror.c (8907B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: mirror.c 8 * Purpose: BCMX mirroring CLI commands 9 */ 10 11 #include <bcm/mirror.h> 12 #include <bcm/error.h> 13 #include <bcmx/bcmx.h> 14 #include <bcmx/mirror.h> 15 16 #include <sal/appl/io.h> 17 18 #include <appl/diag/shell.h> 19 #include <appl/diag/system.h> 20 #include <appl/diag/parse.h> 21 22 #include "bcmx.h" 23 #include <appl/diag/diag.h> 24 25 char bcmx_cmd_mirror_usage[] = 26 "Get/set mirroring configuration. \nSyntax:\n" 27 " mirror -- Show the mirror mode and dest port\n" 28 " mirror [init | disable | enable <options>]\n" 29 " -- Set the mirroring configuration\n" 30 #ifndef COMPILER_STRING_CONST_LIMIT 31 "Enable Options:\n" 32 " Mode=[L2|L3|Off] -- Set the mirror mode\n" 33 " DESTport=<user-port> -- Set the mirror destination port\n" 34 " IngressPorts=<user-port-list> -- Enable/disable ingress mirroring\n" 35 " EgressPorts=<user-port-list> -- Enable/disable egress mirroring\n" 36 #endif 37 "\nNote: Not all modes are supported in all systems\n"; 38 39 cmd_result_t 40 bcmx_cmd_mirror(int unit, args_t *args) 41 { 42 parse_table_t pt; 43 int mode; 44 int enable = 1; /* Should ports listed have mirroring enabled or dis */ 45 char *iport; 46 char *eport; 47 char *dport; 48 bcmx_lplist_t ports; 49 bcmx_lport_t lport; 50 int count; 51 cmd_result_t cmd_rv = CMD_OK; 52 int rv; 53 char *subcmd = NULL; 54 int mirror_mode; 55 bcmx_uport_t uport; 56 57 static char *modeList[] = {"L2", "L3", "Off", NULL}; 58 59 if ((subcmd = ARG_GET(args)) == NULL) { 60 int first; 61 int val; 62 63 bcmx_mirror_mode_get(&mirror_mode); 64 bcmx_mirror_to_get(&lport); 65 66 if (mirror_mode == BCM_MIRROR_DISABLE) { 67 sal_printf("Mirroring is currently disabled.\n"); 68 } else { 69 sal_printf("Current mirror mode is: %s.\n", 70 mirror_mode == BCM_MIRROR_L2 ? "L2" : "L3"); 71 if (!BCMX_LPORT_VALID(lport)) { 72 sal_printf("Warning: mirror to port is invalid\n"); 73 } 74 } 75 if (BCMX_LPORT_VALID(lport)) { 76 sal_printf("Current mirror to uport is %s (lport 0x%x).\n", 77 bcmx_lport_to_uport_str(lport), lport); 78 } 79 first = TRUE; 80 BCMX_FOREACH_LPORT(lport) { 81 if (bcmx_mirror_ingress_get(lport, &val) == BCM_E_NONE) { 82 if (val) { 83 if (first) { 84 sal_printf(" Ingress uport: %s", 85 bcmx_lport_to_uport_str(lport)); 86 first = FALSE; 87 } else { 88 sal_printf(" %s", bcmx_lport_to_uport_str(lport)); 89 } 90 } 91 } 92 } 93 if (!first) { 94 sal_printf("\n"); 95 } 96 first = TRUE; 97 BCMX_FOREACH_LPORT(lport) { 98 if (bcmx_mirror_egress_get(lport, &val) == BCM_E_NONE) { 99 if (val) { 100 if (first) { 101 sal_printf(" Egress uport: %s", 102 bcmx_lport_to_uport_str(lport)); 103 first = FALSE; 104 } else { 105 sal_printf(" %s", bcmx_lport_to_uport_str(lport)); 106 } 107 108 } 109 } 110 } 111 if (!first) { 112 sal_printf("\n"); 113 } 114 115 return CMD_OK; 116 } 117 118 if (! sal_strcasecmp(subcmd, "init")) { 119 sal_printf("Mirror init returns %d\n", bcmx_mirror_init()); 120 return CMD_OK; 121 } else if (! sal_strcasecmp(subcmd, "disable")) { 122 sal_printf("Mirror mode(disable) returns %d\n", 123 bcmx_mirror_mode_set(BCM_MIRROR_DISABLE)); 124 } else if (! sal_strcasecmp(subcmd, "enable")) { 125 126 parse_table_init(unit, &pt); 127 parse_table_add(&pt, "Mode", PQ_NO_EQ_OPT | PQ_MULTI, 128 0, &mode, modeList); 129 parse_table_add(&pt, "DESTport", PQ_NO_EQ_OPT | PQ_STRING, 130 0, &dport, NULL); 131 parse_table_add(&pt, "IngressPorts", PQ_NO_EQ_OPT | PQ_STRING, 132 0, &iport, NULL); 133 parse_table_add(&pt, "EgressPorts", PQ_NO_EQ_OPT | PQ_STRING, 134 0, &eport, NULL); 135 136 /* 137 * Check for each operation indicated and carry out sequentially 138 * Be careful about memory leaks with lplist. Each segment should 139 * init and free the list consistently. 140 */ 141 142 if (parse_arg_eq(args, &pt) < 0) { 143 sal_printf("%s: Error: Unknown option: %s\n", ARG_CMD(args), 144 ARG_CUR(args)); 145 parse_arg_eq_done(&pt); 146 return(CMD_FAIL); 147 } 148 149 /* Set dest port first to make things happen right */ 150 151 if (pt.pt_entries[1].pq_type & PQ_PARSED) { /* Destination port given */ 152 uport = bcmx_uport_parse(dport, NULL); 153 lport = bcmx_uport_to_lport(uport); 154 if (lport == BCMX_NO_SUCH_LPORT) { 155 sal_printf("%s: bad destination port given: %s\n", 156 ARG_CMD(args), dport); 157 parse_arg_eq_done(&pt); 158 return CMD_FAIL; 159 } 160 rv = bcmx_mirror_to_set(lport); 161 if (rv < 0) { 162 sal_printf("%s: bcmx_mirror_to_set failed, %d: %s\n", 163 ARG_CMD(args), rv, bcm_errmsg(rv)); 164 parse_arg_eq_done(&pt); 165 return(CMD_FAIL); 166 } 167 } 168 169 if (pt.pt_entries[2].pq_type & PQ_PARSED) { /* Ingress ports given */ 170 if (bcmx_lplist_init(&ports, 0, 0) < 0) { 171 sal_printf("%s: Could not init port list\n", 172 ARG_CMD(args)); 173 parse_arg_eq_done(&pt); 174 return CMD_FAIL; 175 } 176 177 if (bcmx_lplist_parse(&ports, iport) < 0) { 178 sal_printf("%s: Could not parse user port list: %s\n", 179 ARG_CMD(args), iport); 180 cmd_rv = CMD_FAIL; 181 } else { 182 BCMX_LPLIST_ITER(ports, lport, count) { 183 rv = bcmx_mirror_ingress_set(lport, enable); 184 if (rv < 0) { 185 sal_printf("%s: Could not %s ingress mirroring for %s\n", 186 ARG_CMD(args), 187 "enable", 188 bcmx_lport_to_uport_str(lport)); 189 cmd_rv = CMD_FAIL; 190 break; 191 } 192 } 193 } 194 195 bcmx_lplist_free(&ports); 196 } 197 198 if ((cmd_rv == CMD_OK) && (pt.pt_entries[3].pq_type & PQ_PARSED)) { 199 /* Engress ports given */ 200 if (bcmx_lplist_init(&ports, 0, 0) < 0) { 201 sal_printf("%s: Could not init port list\n", 202 ARG_CMD(args)); 203 parse_arg_eq_done(&pt); 204 return CMD_FAIL; 205 } 206 207 if (bcmx_lplist_parse(&ports, eport) < 0) { 208 sal_printf("Could not parse user port list: %s\n", eport); 209 cmd_rv = CMD_FAIL; 210 } else { 211 BCMX_LPLIST_ITER(ports, lport, count) { 212 rv = bcmx_mirror_egress_set(lport, enable); 213 if (rv < 0) { 214 sal_printf("%s: Could not %s egress mirroring for %s\n", 215 ARG_CMD(args), 216 "enable", 217 bcmx_lport_to_uport_str(lport)); 218 cmd_rv = CMD_FAIL; 219 break; 220 } 221 } 222 } 223 224 bcmx_lplist_free(&ports); 225 } 226 227 if (pt.pt_entries[0].pq_type & PQ_PARSED) { /* Mode given */ 228 switch (mode) { 229 case 0: mode = BCM_MIRROR_L2; break; 230 case 1: mode = BCM_MIRROR_L2_L3; break; 231 case 2: mode = BCM_MIRROR_DISABLE; break; 232 default: 233 sal_printf("%s: Unknown mode, %d.\n", ARG_CMD(args), mode); 234 parse_arg_eq_done(&pt); 235 return CMD_FAIL; 236 } 237 238 rv = bcmx_mirror_mode_set(mode); 239 if (rv < 0) { 240 sal_printf("%s: bcmx_mirror_mode_set failed, %d: %s\n", 241 ARG_CMD(args), rv, bcm_errmsg(rv)); 242 parse_arg_eq_done(&pt); 243 return CMD_FAIL; 244 } 245 } 246 247 parse_arg_eq_done(&pt); 248 249 } else { 250 sal_printf("Unknown mirror subcommand: %s\n", subcmd); 251 return CMD_USAGE; 252 } 253 return cmd_rv; 254 } 255