macsec.c (9190B)
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 * Packet Watcher 8 */ 9 10 #include <sal/types.h> 11 #include <shared/bsl.h> 12 #ifdef INCLUDE_MACSEC 13 14 #ifndef __KERNEL__ 15 #include <sys/types.h> 16 #include <netinet/in.h> 17 #endif 18 19 #include <soc/debug.h> 20 #include <soc/cm.h> 21 22 #include <sal/appl/io.h> 23 #include <sal/appl/sal.h> 24 #include <sal/core/thread.h> 25 #include <sal/core/sync.h> 26 #include <sal/core/spl.h> 27 #include <sal/core/libc.h> 28 29 #include <appl/diag/shell.h> 30 #include <appl/diag/parse.h> 31 #include <appl/diag/system.h> 32 #include <appl/diag/decode.h> 33 #include <appl/diag/dport.h> 34 35 #include <bcm/macsec.h> 36 #include <bcm/error.h> 37 38 #include <bcm_int/common/macsec_cmn.h> 39 #include <bcm_int/esw/port.h> 40 #include <soc/macsecphy.h> 41 42 #include <bmacsec.h> 43 #include <bmacsec_cli.h> 44 45 #ifdef PLISIM 46 #define MACSEC_SIM 1 47 /* 48 #define MACSEC_SIM_DEBUG 1 49 */ 50 #endif 51 52 /* 53 * This variable stores the current BCM unit. 54 */ 55 static int _macsec_bcm_unit = -1; 56 57 #ifdef MACSEC_SIM 58 59 typedef struct _macsec_dev_info_s { 60 char *name; 61 bcm_macsec_core_t core_type; 62 int num_port; 63 } _macsec_dev_info_t; 64 65 static _macsec_dev_info_t macsec_dev_info_table[] = { 66 {"BCM54580", BCM_MACSEC_CORE_BCM5458X, 8}, 67 {"BCM8729", BCM_MACSEC_CORE_BCM8729, 4}, 68 {NULL, 0, 0}, 69 }; 70 71 typedef struct _macsec_sim_io_res_s { 72 uint32 dev_addr; 73 uint32 dev_port; 74 uint32 io_addr; 75 int res_size; 76 #define MACSEC_SIM_MAX_DATA_SIZE 16 77 uint32 data[MACSEC_SIM_MAX_DATA_SIZE]; 78 struct _macsec_sim_io_res_s *next; 79 } _macsec_sim_io_res_t; 80 81 static _macsec_sim_io_res_t *io_res_bucket[16]; 82 83 int macsec_sim_init() 84 { 85 int ii; 86 87 for (ii = 0; ii < 16; ii++) { 88 io_res_bucket[ii] = NULL; 89 } 90 return 0; 91 } 92 93 void _dump_res(int bucket) 94 { 95 _macsec_sim_io_res_t **pentry; 96 int loop_cnt = 0; 97 98 pentry = &io_res_bucket[bucket]; 99 cli_out("Dumping bucket %d\n", bucket); 100 while(*pentry) { 101 cli_out("0x%08x : %d %d %d \n", (*pentry)->io_addr, 102 (*pentry)->res_size, 103 (*pentry)->dev_addr, 104 (*pentry)->dev_port); 105 pentry = &(*pentry)->next; 106 if (++loop_cnt > 10000) { 107 break; 108 } 109 } 110 } 111 112 #define MACSEC_SIM_RES_BUCKET(io) (((io) >> 20) & 0xf) 113 114 _macsec_sim_io_res_t* _macsec_sim_find_res(int dev_addr, int dev_port, 115 int wordSz, uint32 io_addr) 116 { 117 _macsec_sim_io_res_t **pentry, *res; 118 int ii, loop_cnt = 0; 119 120 res = io_res_bucket[MACSEC_SIM_RES_BUCKET(io_addr)]; 121 122 while(res && ((res->io_addr != io_addr) || 123 (res->dev_addr != dev_addr))) { 124 res = res->next; 125 if (++loop_cnt > 1000000) { 126 _dump_res(MACSEC_SIM_RES_BUCKET(io_addr)); 127 return NULL; 128 } 129 } 130 131 if (res == NULL) { 132 res = sal_alloc(sizeof(_macsec_sim_io_res_t), "macsec sim res"); 133 for (ii = 0; ii < MACSEC_SIM_MAX_DATA_SIZE; ii++) { 134 res->data[ii] = 0xbabeadda; 135 } 136 res->io_addr = io_addr; 137 res->res_size = wordSz; 138 res->dev_addr = dev_addr; 139 res->next = NULL; 140 141 pentry = &io_res_bucket[MACSEC_SIM_RES_BUCKET(io_addr)]; 142 res->next = *pentry; 143 *pentry = res; 144 } 145 146 147 return res; 148 } 149 150 static int _macsec_sim_do_io_op(_macsec_sim_io_res_t *res, 151 bmacsec_io_op_t op, 152 int wordSz, void *data) 153 { 154 int ii, read; 155 156 read = ((op == BMACSEC_IO_TBL_RD) || 157 (op == BMACSEC_IO_REG_RD)) ? 1 : 0; 158 159 if (read) { 160 for (ii = 0; ii < wordSz; ii++) { 161 *((uint32*)data + ii) = res->data[ii]; 162 } 163 } else { 164 for (ii = 0; ii < wordSz; ii++) { 165 res->data[ii] = *((uint32*)data + ii); 166 } 167 } 168 #if defined(MACSEC_SIM_DEBUG) 169 cli_out("SIM %s (0x%08x): 0x", (read ? "READ" : "WRITE"), res->io_addr); 170 for (ii = 0; ii < wordSz; ii++) { 171 cli_out("%08x ", res->data[ii]); 172 } 173 cli_out("\n"); 174 #endif 175 return 0; 176 } 177 178 static int macsec_sim_inited = 0; 179 180 int macsec_sim_io_handler(bcm_macsec_dev_addr_t devaddr,/* device addr*/ 181 int dev_port, /* dev port index */ 182 bmacsec_io_op_t op, /* I/O operation */ 183 uint32 io_addr, /* I/O address */ 184 int wordSz, /* Word size */ 185 int num_entry, 186 uint32 *data) 187 { 188 _macsec_sim_io_res_t *res; 189 190 if (macsec_sim_inited == 0) { 191 macsec_sim_init(); 192 macsec_sim_inited = 1; 193 } 194 195 res = _macsec_sim_find_res(devaddr, dev_port, wordSz, io_addr); 196 197 if (res == NULL) { 198 return -1; 199 } 200 _macsec_sim_do_io_op(res, op, wordSz, data); 201 return 0; 202 } 203 204 static int _macsec_sim_port_create(char *dev_type) 205 { 206 int dev, port, p, num_devs = 1, num_port; 207 bcm_macsec_port_config_t pCfg; 208 _macsec_dev_info_t *dev_info; 209 int dev_addr, unit, sw_port = 1; 210 211 /* lookup device info table */ 212 dev_info = macsec_dev_info_table; 213 while (dev_info->name && sal_strcasecmp(dev_info->name, dev_type)) { 214 dev_info++; 215 } 216 217 if (dev_info->name == NULL) { 218 cli_out("Unknown device : %s\n", dev_type); 219 return CMD_FAIL; 220 } 221 222 unit = _macsec_bcm_unit; 223 sw_port = 1; /* Start using switch port 1 onwards, as CPU port is often zero */ 224 num_port = dev_info->num_port; 225 for (dev = 0; dev < num_devs; dev++) { 226 for (port = 0; port < num_port; port++, sw_port++) { 227 /* create port itentifier */ 228 p = SOC_MACSEC_PORTID(unit, sw_port); 229 dev_addr = soc_property_port_get(unit, port, 230 spn_MACSEC_DEV_ADDR, -1); 231 if (dev_addr < 0) { 232 cli_out("No %s property specified for port u=%d/p=%d\n", 233 spn_MACSEC_DEV_ADDR, unit, sw_port); 234 continue; 235 } 236 bmacsec_port_destroy(p); 237 bmacsec_port_create(p, dev_info->core_type, 238 dev_addr, port, macsec_sim_io_handler); 239 cli_out("SIM: %d/%d is now MACSEC enabled.\n", unit, sw_port); 240 241 242 bcm_macsec_port_config_get(unit, sw_port, &pCfg); 243 pCfg.flags |= BCM_MACSEC_PORT_ENABLE; 244 pCfg.max_frame = 1518; 245 bcm_macsec_port_config_set(unit, sw_port, &pCfg); 246 } 247 } 248 return 0; 249 } 250 251 #endif /* MACSEC_SIM */ 252 253 char sh_macsec_usage[] = 254 "Call macsec help for more information.\n" 255 "\n"; 256 257 258 static int 259 macsec_port_sym_parse(char *pname, bcm_macsec_dev_addr_t *dev_addr, 260 int *dev_port, bmacsec_port_t *pid) 261 { 262 bcm_port_config_t pcfg; 263 pbmp_t pbm; 264 soc_port_t p, dport; 265 int unit = _macsec_bcm_unit; 266 267 if (unit < 0) { 268 return -1; 269 } 270 271 if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) { 272 return CMD_FAIL; 273 } 274 275 BCM_PBMP_ASSIGN(pbm, pcfg.port); 276 277 if (BCM_PBMP_IS_NULL(pbm)) { 278 return -1; 279 } 280 281 DPORT_BCM_PBMP_ITER(unit, pbm, dport, p) { 282 if (sal_strcasecmp(pname, BCM_PORT_NAME(unit, p)) == 0) { 283 /* 284 * Fill device address and device port info. 285 */ 286 *dev_addr = soc_property_port_get(unit, p, 287 spn_MACSEC_DEV_ADDR, -1); 288 *dev_port = soc_property_port_get(unit, p, 289 spn_MACSEC_PORT_INDEX, -1); 290 *pid = SOC_MACSEC_PORTID(unit, p); 291 return 0; 292 } 293 } 294 295 return -1; 296 } 297 298 299 /* 300 * Function: sh_macsec 301 * Purpose: MACSec comands 302 * Parameters: u - SOC unit # 303 * Returns: CMD_OK/CMD_FAIL/ 304 */ 305 cmd_result_t 306 sh_macsec(int u, args_t *a) 307 { 308 int rv = CMD_USAGE; 309 bmacsec_cli_cfg_t bmacsec_cli_cfg; 310 #ifdef MACSEC_SIM 311 char *arg; 312 char *dev_type; 313 #endif 314 int num_a; 315 static int macsec_cli_registered = 0; 316 317 _macsec_bcm_unit = u; 318 319 if(!macsec_cli_registered) { 320 bmacsec_cli_cfg.port_sym_parse = macsec_port_sym_parse; 321 #ifdef MACSEC_SIM 322 bmacsec_cli_cfg.dev_io_f = macsec_sim_io_handler; 323 #else 324 bmacsec_cli_cfg.dev_io_f = NULL; 325 #endif 326 rv = bmacsec_cli_register(&bmacsec_cli_cfg); 327 if(rv < 0) { 328 cli_out("Failed to register MACSEC CLI\n"); 329 return CMD_FAIL; 330 } 331 332 macsec_cli_registered = 1; 333 } 334 335 #ifdef MACSEC_SIM 336 arg = ARG_GET(a); 337 if (arg != NULL && sal_strcasecmp(arg, "sim_init") == 0) { 338 /* get the device to simulate */ 339 dev_type = ARG_GET(a); 340 if (!dev_type) { 341 dev_type = "BCM8729"; 342 } 343 return _macsec_sim_port_create(dev_type); 344 } 345 #endif 346 num_a = a->a_argc - 1; 347 num_a = (num_a < 0) ? 0 : num_a; 348 rv = bmacsec_handle_cmd(num_a, &a->a_argv[1]); 349 a->a_arg = a->a_argc; /* Consume all args */ 350 _macsec_bcm_unit = -1; 351 return rv; 352 } 353 354 #endif /* INCLUDE_MACSEC */