Commit 684a4ad8 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

RTU: provide mirroring configuration in SHM

parent 7c225eef
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
/* Maximum number of supported VLANs */ /* Maximum number of supported VLANs */
#define NUM_VLANS 4096 #define NUM_VLANS 4096
/* Currently only one port mirror setup is allowed */
#define NUM_MIRROR 1
#define ETH_ALEN 6 #define ETH_ALEN 6
#define ETH_ALEN_STR 18 #define ETH_ALEN_STR 18
...@@ -124,13 +127,25 @@ struct rtu_vlan_table_entry { ...@@ -124,13 +127,25 @@ struct rtu_vlan_table_entry {
int drop; /* 1: drop the packet (VLAN not registered) */ int drop; /* 1: drop the packet (VLAN not registered) */
}; };
/**
* \brief RTU mirroring configuration
*/
struct rtu_mirror_info {
int en; /* Mirroring enabled flag */
uint32_t imask; /* Ingress source port mask */
uint32_t emask; /* Egress source port mask */
uint32_t dmask; /* Destination port mask */
};
/* This is the overall structure stored in shared memory */ /* This is the overall structure stored in shared memory */
#define RTU_SHMEM_VERSION 3 /* Version 3, changed wrs_shm_head */ #define RTU_SHMEM_VERSION 4 /* Version 3, changed wrs_shm_head */
struct rtu_shmem_header { struct rtu_shmem_header {
struct rtu_filtering_entry *filters; struct rtu_filtering_entry *filters;
struct rtu_vlan_table_entry *vlans; struct rtu_vlan_table_entry *vlans;
struct rtu_mirror_info *mirror;
unsigned long filters_offset; unsigned long filters_offset;
unsigned long vlans_offset; unsigned long vlans_offset;
unsigned long mirror_offset;
}; };
#endif /* __LIBWR_RTU_SHMEM_H__ */ #endif /* __LIBWR_RTU_SHMEM_H__ */
...@@ -518,12 +518,22 @@ struct dump_info vlan_info[] = { ...@@ -518,12 +518,22 @@ struct dump_info vlan_info[] = {
DUMP_FIELD(int, drop), DUMP_FIELD(int, drop),
}; };
#undef DUMP_STRUCT
#define DUMP_STRUCT struct rtu_mirror_info
struct dump_info mirror_info[] = {
DUMP_FIELD(int, en),
DUMP_FIELD(uint32_t, imask),
DUMP_FIELD(uint32_t, emask),
DUMP_FIELD(uint32_t, dmask),
};
int dump_rtu_mem(struct wrs_shm_head *head) int dump_rtu_mem(struct wrs_shm_head *head)
{ {
struct rtu_shmem_header *rtu_h; struct rtu_shmem_header *rtu_h;
struct rtu_filtering_entry *rtu_filters; struct rtu_filtering_entry *rtu_filters;
struct rtu_filtering_entry *rtu_filters_cur; struct rtu_filtering_entry *rtu_filters_cur;
struct rtu_vlan_table_entry *rtu_vlans; struct rtu_vlan_table_entry *rtu_vlans;
struct rtu_mirror_info *rtu_mirror;
int i, j; int i, j;
char prefix[64]; char prefix[64];
...@@ -535,8 +545,9 @@ int dump_rtu_mem(struct wrs_shm_head *head) ...@@ -535,8 +545,9 @@ int dump_rtu_mem(struct wrs_shm_head *head)
rtu_h = (void *)head + head->data_off; rtu_h = (void *)head + head->data_off;
rtu_filters = wrs_shm_follow(head, rtu_h->filters); rtu_filters = wrs_shm_follow(head, rtu_h->filters);
rtu_vlans = wrs_shm_follow(head, rtu_h->vlans); rtu_vlans = wrs_shm_follow(head, rtu_h->vlans);
rtu_mirror = wrs_shm_follow(head, rtu_h->mirror);
if ((!rtu_filters) || (!rtu_vlans)) { if ((!rtu_filters) || (!rtu_vlans) || (!rtu_mirror)) {
fprintf(stderr, "dump rtu: cannot follow pointer in shm\n"); fprintf(stderr, "dump rtu: cannot follow pointer in shm\n");
return -1; return -1;
} }
...@@ -562,6 +573,11 @@ int dump_rtu_mem(struct wrs_shm_head *head) ...@@ -562,6 +573,11 @@ int dump_rtu_mem(struct wrs_shm_head *head)
sprintf(prefix,"rtu.vlan.%d",i); sprintf(prefix,"rtu.vlan.%d",i);
dump_many_fields(rtu_vlans, vlan_info, ARRAY_SIZE(vlan_info),prefix); dump_many_fields(rtu_vlans, vlan_info, ARRAY_SIZE(vlan_info),prefix);
} }
sprintf(prefix, "rtu.mirror");
dump_many_fields(rtu_mirror, mirror_info, ARRAY_SIZE(mirror_info),
prefix);
return 0; return 0;
} }
......
...@@ -642,23 +642,27 @@ int rtu_enable_mirroring(int ena) ...@@ -642,23 +642,27 @@ int rtu_enable_mirroring(int ena)
* @param dmask Destination port mask * @param dmask Destination port mask
* @return error code. * @return error code.
*/ */
int rtu_cfg_mirroring(int en, uint32_t imask, uint32_t emask, uint32_t dmask) int rtu_cfg_mirroring(struct rtu_mirror_info *cfg)
{ {
/* write destination port mask - to which port/-s mirrored traffic will be /* if mirroring disabled (en == 0) zero all masks */
* sent */ /* if mirroring enabled (en == 1) write only non-zero masks */
if (en == 0 || dmask != 0) {
/* write destination port mask - to which port/-s mirrored traffic will
* be sent
*/
if (cfg->en == 0 || cfg->dmask != 0) {
rtu_wr(RX_MP_R0, 0); rtu_wr(RX_MP_R0, 0);
rtu_wr(RX_MP_R1, RTU_RX_MP_R1_MASK_W(dmask)); rtu_wr(RX_MP_R1, RTU_RX_MP_R1_MASK_W(cfg->dmask));
} }
/* write ingress port mask - source of mirrored traffic */ /* write ingress port mask - source of mirrored traffic */
if (en == 0 || imask != 0) { if (cfg->en == 0 || cfg->imask != 0) {
rtu_wr(RX_MP_R0, RTU_RX_MP_R0_DST_SRC); rtu_wr(RX_MP_R0, RTU_RX_MP_R0_DST_SRC);
rtu_wr(RX_MP_R1, RTU_RX_MP_R1_MASK_W(imask)); rtu_wr(RX_MP_R1, RTU_RX_MP_R1_MASK_W(cfg->imask));
} }
/* write egress port mask - source of mirrored traffic */ /* write egress port mask - source of mirrored traffic */
if (en == 0 || emask != 0) { if (cfg->en == 0 || cfg->emask != 0) {
rtu_wr(RX_MP_R0, RTU_RX_MP_R0_DST_SRC | RTU_RX_MP_R0_RX_TX); rtu_wr(RX_MP_R0, RTU_RX_MP_R0_DST_SRC | RTU_RX_MP_R0_RX_TX);
rtu_wr(RX_MP_R1, RTU_RX_MP_R1_MASK_W(emask)); rtu_wr(RX_MP_R1, RTU_RX_MP_R1_MASK_W(cfg->emask));
} }
return 0; return 0;
......
...@@ -98,7 +98,7 @@ void rtu_clear_irq(void); ...@@ -98,7 +98,7 @@ void rtu_clear_irq(void);
// PORT MIRRORING // PORT MIRRORING
int rtu_enable_mirroring(int ena); int rtu_enable_mirroring(int ena);
int rtu_cfg_mirroring(int en, uint32_t imask, uint32_t emask, uint32_t dmask); int rtu_cfg_mirroring(struct rtu_mirror_info *cfg);
int rtu_get_mirroring(int *en, uint32_t *imask, uint32_t *emask, uint32_t *dmask); int rtu_get_mirroring(int *en, uint32_t *imask, uint32_t *emask, uint32_t *dmask);
#endif /*__WHITERABBIT_RTU_DRV_H*/ #endif /*__WHITERABBIT_RTU_DRV_H*/
...@@ -93,6 +93,11 @@ static unsigned long aging_time = DEFAULT_AGING_TIME; ...@@ -93,6 +93,11 @@ static unsigned long aging_time = DEFAULT_AGING_TIME;
*/ */
static struct rtu_vlan_table_entry *vlan_tab; static struct rtu_vlan_table_entry *vlan_tab;
/**
* Mirror of port mirroring configuration
*/
static struct rtu_mirror_info *mirror_cfg;
/** /**
* \brief Mutex used to synchronise concurrent access to the filtering database. * \brief Mutex used to synchronise concurrent access to the filtering database.
*/ */
...@@ -110,6 +115,7 @@ static int hw_request(int type, struct rtu_addr addr, ...@@ -110,6 +115,7 @@ static int hw_request(int type, struct rtu_addr addr,
static void clean_fd(void); static void clean_fd(void);
static void clean_vd(void); static void clean_vd(void);
static void clean_mc(void);
static void rtu_hw_commit(void); static void rtu_hw_commit(void);
static void rtu_fd_commit(void); static void rtu_fd_commit(void);
...@@ -200,7 +206,31 @@ int rtu_fd_init(uint16_t poly, unsigned long aging) ...@@ -200,7 +206,31 @@ int rtu_fd_init(uint16_t poly, unsigned long aging)
(sizeof(*vlan_tab) * NUM_VLANS + 7) & ~7; (sizeof(*vlan_tab) * NUM_VLANS + 7) & ~7;
} }
if ((!rtu_htab) || (!vlan_tab)) { if (!rtu_hdr->mirror) {
/* for first RTUd run */
pr_info("Allocating a new, port mirroring config\n");
mirror_cfg = wrs_shm_alloc(rtu_port_shmem,
sizeof(*mirror_cfg) * NUM_MIRROR);
rtu_hdr->mirror = mirror_cfg;
rtu_hdr->mirror_offset =
(void *)mirror_cfg - (void *)rtu_port_shmem;
pr_debug("Clean vlan database.\n");
clean_mc(); /* clean port mirroring config */
} else {
pr_info("Using existing port mirroring config.\n");
/* next RTUd runs */
rtu_hdr->mirror =
(void *)rtu_port_shmem + rtu_hdr->mirror_offset;
mirror_cfg = (void *)rtu_hdr->mirror;
/* move data_size to have have similar behavior like
* wrs_shm_alloc, needed for future allocations
* force 8-alignment
*/
rtu_port_shmem->data_size +=
(sizeof(*mirror_cfg) * NUM_MIRROR + 7) & ~7;
}
if ((!rtu_htab) || (!vlan_tab) || (!mirror_cfg)) {
pr_error("%s: Cannot allocate mem in shmem\n", __func__); pr_error("%s: Cannot allocate mem in shmem\n", __func__);
return -1; return -1;
} }
...@@ -503,6 +533,23 @@ static void clean_vd(void) ...@@ -503,6 +533,23 @@ static void clean_vd(void)
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_END); wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_END);
} }
/**
* Port mirroring config initialization (disabled by default).
*/
static void clean_mc(void)
{
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_BEGIN);
mirror_cfg[0].en = 0;
mirror_cfg[0].imask = 0x0;
mirror_cfg[0].emask = 0x0;
mirror_cfg[0].dmask = 0x0;
rtu_enable_mirroring(mirror_cfg[0].en);
rtu_cfg_mirroring(mirror_cfg);
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_END);
}
/** /**
* \brief Updates the age of filtering entries accessed in the last period. * \brief Updates the age of filtering entries accessed in the last period.
*/ */
...@@ -777,3 +824,23 @@ void rtu_fd_create_vlan_entry(int vid, uint32_t port_mask, uint8_t fid, ...@@ -777,3 +824,23 @@ void rtu_fd_create_vlan_entry(int vid, uint32_t port_mask, uint8_t fid,
rtu_write_vlan_entry(vid, &vlan_tab[vid]); rtu_write_vlan_entry(vid, &vlan_tab[vid]);
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_END); wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_END);
} }
void rtu_fd_write_mirror_config(int en, uint32_t imask, uint32_t emask,
uint32_t dmask)
{
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_BEGIN);
mirror_cfg[0].en = en;
/* update masks in SHM only if non-zero, or if disabling mirroring */
if (en == 0 || imask != 0)
mirror_cfg[0].imask = imask;
if (en == 0 || emask != 0)
mirror_cfg[0].emask = emask;
if (en == 0 || dmask != 0)
mirror_cfg[0].dmask = dmask;
rtu_enable_mirroring(0);
rtu_cfg_mirroring(mirror_cfg);
rtu_enable_mirroring(en);
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_END);
}
...@@ -366,9 +366,7 @@ int rtudexp_mirror(const struct minipc_pd *pd, uint32_t *args, void *ret) ...@@ -366,9 +366,7 @@ int rtudexp_mirror(const struct minipc_pd *pd, uint32_t *args, void *ret)
return *p_ret; return *p_ret;
} }
rtu_enable_mirroring(0); rtu_fd_write_mirror_config(enable, imask, emask, dmask);
rtu_cfg_mirroring(enable, imask, emask, dmask);
rtu_enable_mirroring(enable);
return *p_ret; return *p_ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment