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

RTU: provide mirroring configuration in SHM

parent 7c225eef
......@@ -12,6 +12,9 @@
/* Maximum number of supported VLANs */
#define NUM_VLANS 4096
/* Currently only one port mirror setup is allowed */
#define NUM_MIRROR 1
#define ETH_ALEN 6
#define ETH_ALEN_STR 18
......@@ -124,13 +127,25 @@ struct rtu_vlan_table_entry {
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 */
#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_filtering_entry *filters;
struct rtu_vlan_table_entry *vlans;
struct rtu_mirror_info *mirror;
unsigned long filters_offset;
unsigned long vlans_offset;
unsigned long mirror_offset;
};
#endif /* __LIBWR_RTU_SHMEM_H__ */
......@@ -518,12 +518,22 @@ struct dump_info vlan_info[] = {
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)
{
struct rtu_shmem_header *rtu_h;
struct rtu_filtering_entry *rtu_filters;
struct rtu_filtering_entry *rtu_filters_cur;
struct rtu_vlan_table_entry *rtu_vlans;
struct rtu_mirror_info *rtu_mirror;
int i, j;
char prefix[64];
......@@ -535,8 +545,9 @@ int dump_rtu_mem(struct wrs_shm_head *head)
rtu_h = (void *)head + head->data_off;
rtu_filters = wrs_shm_follow(head, rtu_h->filters);
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");
return -1;
}
......@@ -562,6 +573,11 @@ int dump_rtu_mem(struct wrs_shm_head *head)
sprintf(prefix,"rtu.vlan.%d",i);
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;
}
......
......@@ -642,23 +642,27 @@ int rtu_enable_mirroring(int ena)
* @param dmask Destination port mask
* @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
* sent */
if (en == 0 || dmask != 0) {
/* if mirroring disabled (en == 0) zero all masks */
/* if mirroring enabled (en == 1) write only non-zero masks */
/* 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_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 */
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_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 */
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_R1, RTU_RX_MP_R1_MASK_W(emask));
rtu_wr(RX_MP_R1, RTU_RX_MP_R1_MASK_W(cfg->emask));
}
return 0;
......
......@@ -98,7 +98,7 @@ void rtu_clear_irq(void);
// PORT MIRRORING
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);
#endif /*__WHITERABBIT_RTU_DRV_H*/
......@@ -93,6 +93,11 @@ static unsigned long aging_time = DEFAULT_AGING_TIME;
*/
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.
*/
......@@ -110,6 +115,7 @@ static int hw_request(int type, struct rtu_addr addr,
static void clean_fd(void);
static void clean_vd(void);
static void clean_mc(void);
static void rtu_hw_commit(void);
static void rtu_fd_commit(void);
......@@ -200,7 +206,31 @@ int rtu_fd_init(uint16_t poly, unsigned long aging)
(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__);
return -1;
}
......@@ -503,6 +533,23 @@ static void clean_vd(void)
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.
*/
......@@ -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]);
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)
return *p_ret;
}
rtu_enable_mirroring(0);
rtu_cfg_mirroring(enable, imask, emask, dmask);
rtu_enable_mirroring(enable);
rtu_fd_write_mirror_config(enable, imask, emask, dmask);
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