openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 */