Commit 7c225eef authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

RTU: add option to rtu_stat to enable port mirroring

parent 21ce8654
......@@ -177,6 +177,11 @@ void show_help(char *prgname)
fprintf(stderr, " vlan <vid> <fid> <port_mask> [<drop>, <prio>, <has_prio>, <prio_override>]:\n"
" Add VLAN entry with vid, fid, mask and drop flag;\n"
" write mask=0x0 and drop=1 to remove the VLAN\n");
fprintf(stderr, " mirror ingress <src_port> <dst_port>: Enable mirroring of ingress traffic\n"
" from src_port to dst_port\n");
fprintf(stderr, " mirror egress <src_port> <dst_port>: Enable mirroring of egress traffic\n"
" from src_port to dst_port\n");
fprintf(stderr, " mirror off: Turn off port mirroring\n");
fprintf(stderr, "\n");
fprintf(stderr, "Where:\n");
fprintf(stderr, " <mac> MAC address to be used in the RTU rule;\n"
......@@ -401,6 +406,96 @@ int read_port_mask(char *mask, int nports)
return -1;
}
int port_to_mask(char *port, int nports)
{
int portnum;
portnum = read_port(port, nports);
if (portnum >= 0)
return 1 << (portnum-1);
else
return -1;
}
int set_mirroring(int nports, int argc, char **argv)
{
int val, ret;
int imask, emask, dmask;
int s_port, d_port;
/* mirror ingress <src_port> <dst_port> */
/* mirror egress <src_port> <dst_port> */
/* mirror off */
/* mirror <imask> <emask> <dmask> */
/*------------------------------------------*/
/* mirror off */
if (argc == 1 && !strcmp(argv[0], "off")) {
printf("Turning off port mirroring\n");
ret = minipc_call(rtud_ch, MINIPC_TIMEOUT, &rtud_export_mirror,
&val, 0, 0, 0, 0);
/*------------------------------------------*/
/* ingress <src_port> <dst_port> */
} else if (argc == 3 && !strcmp(argv[0], "ingress")) {
s_port = read_port(argv[1], nports);
if (s_port < 0)
return s_port;
imask = 1 << (s_port - 1);
d_port = read_port(argv[2], nports);
if (d_port < 0)
return d_port;
dmask = 1 << (d_port - 1);
printf("Configuring ingress mirroring from port %d to port "
"%d\n", s_port, d_port);
ret = minipc_call(rtud_ch, MINIPC_TIMEOUT, &rtud_export_mirror,
&val, 1, imask, 0, dmask);
/*------------------------------------------*/
/* egress <src_port> <dst_port> */
} else if (argc == 3 && !strcmp(argv[0], "egress")) {
s_port = read_port(argv[1], nports);
if (s_port < 0)
return s_port;
emask = 1 << (s_port - 1);
d_port = read_port(argv[2], nports);
if (d_port < 0)
return d_port;
dmask = 1 << (d_port - 1);
printf("Configuring egress mirroring from port %d to port %d\n",
s_port, d_port);
ret = minipc_call(rtud_ch, MINIPC_TIMEOUT, &rtud_export_mirror,
&val, 1, 0, emask, dmask);
/*------------------------------------------*/
/* advanced usecase */
/* mirror <imask> <emask> <dmask> */
} else if (argc == 3) {
imask = read_port_mask(argv[0], nports);
emask = read_port_mask(argv[1], nports);
dmask = read_port_mask(argv[2], nports);
if (imask < 0 || emask < 0 || dmask < 0) {
fprintf(stderr, "Mirror: incorrect mask\n");
return -1;
}
printf("Configuring mirroring with custom masks: ingress 0x%05X"
" egress 0x%05X destination 0x%05X\n", imask,
emask, dmask);
ret = minipc_call(rtud_ch, MINIPC_TIMEOUT, &rtud_export_mirror,
&val, 1, imask, emask, dmask);
/*------------------------------------------*/
/* incorrect parameters */
} else {
fprintf(stderr, "Mirror: incorrect parameters\n");
return -1;
}
return (ret < 0) ? ret : 1;
}
int main(int argc, char **argv)
{
int i, isok;
......@@ -819,6 +914,10 @@ int main(int argc, char **argv)
printf("Vlan command error\n");
exit(1);
}
/* ****************** mirror ************************************************ */
} else if (argc >= 3 && !strcmp(argv[1], "mirror")) {
/* pass only parameters to mirror command */
isok = set_mirroring(nports, argc-2, argv+2);
} else if (argc >= 2
&& !strcmp(argv[1], "list"))
isok = 1;
......
......@@ -616,6 +616,82 @@ int rtu_read_unrecognised_behaviour_on_port(int port)
return read_pcr(port) & RTU_PCR_B_UNREC ? 1 : 0;
}
/**
* \brief Enables/disables port mirroring
* @param ena Enable flag
* @return error code.
*/
int rtu_enable_mirroring(int ena)
{
uint32_t ctr = rtu_rd(RX_CTR);
if (ena == 1)
ctr = ctr | RTU_RX_CTR_MR_ENA;
else
ctr = ctr & (~RTU_RX_CTR_MR_ENA);
rtu_wr(RX_CTR, ctr);
return 0;
}
/**
* \brief Configures port mirroring
* @param imask Ingress port mask
* @param emask Egress port mask
* @param dmask Destination port mask
* @return error code.
*/
int rtu_cfg_mirroring(int en, uint32_t imask, uint32_t emask, uint32_t dmask)
{
/* write destination port mask - to which port/-s mirrored traffic will be
* sent */
if (en == 0 || dmask != 0) {
rtu_wr(RX_MP_R0, 0);
rtu_wr(RX_MP_R1, RTU_RX_MP_R1_MASK_W(dmask));
}
/* write ingress port mask - source of mirrored traffic */
if (en == 0 || 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));
}
/* write egress port mask - source of mirrored traffic */
if (en == 0 || 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));
}
return 0;
}
/**
* \brief Gets port mirroring configuration
* @param en Enabled flag mirroring pointer
* @param imask Ingress port mask pointer
* @param emask Egress port mask pointer
* @param dmask Destination port mask pointer
* @return error code.
*/
int rtu_get_mirroring(int *en, uint32_t *imask, uint32_t *emask, uint32_t *dmask)
{
/* Enabled flag */
if (rtu_rd(RX_CTR) & RTU_RX_CTR_MR_ENA != 0)
*en = 1;
else
*en = 0;
/* destination port mask */
rtu_wr(RX_MP_R0, 0);
*dmask = RTU_RX_MP_R1_MASK_R(rtu_rd(RX_MP_R1));
/* ingress port mask */
rtu_wr(RX_MP_R0, RTU_RX_MP_R0_DST_SRC);
*imask = RTU_RX_MP_R1_MASK_R(rtu_rd(RX_MP_R1));
/* write egress port mask - source of mirrored traffic */
rtu_wr(RX_MP_R0, RTU_RX_MP_R0_DST_SRC | RTU_RX_MP_R0_RX_TX);
*emask = RTU_RX_MP_R1_MASK_R(rtu_rd(RX_MP_R1));
return 0;
}
//---------------------------------------------
// Private Methods
//---------------------------------------------
......
......@@ -96,4 +96,9 @@ void rtu_enable_irq(void);
void rtu_disable_irq(void);
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_get_mirroring(int *en, uint32_t *imask, uint32_t *emask, uint32_t *dmask);
#endif /*__WHITERABBIT_RTU_DRV_H*/
......@@ -336,6 +336,43 @@ int rtudexp_vlan_entry(const struct minipc_pd *pd, uint32_t * args, void *ret)
return *p_ret;
}
int rtudexp_mirror(const struct minipc_pd *pd, uint32_t *args, void *ret)
{
int oper;
int enable;
uint32_t imask, emask, dmask;
int *p_ret = (int *)ret;
enable = (int)args[0];
imask = (int)args[1];
emask = (int)args[2];
dmask = (int)args[3];
*p_ret = 0;
pr_debug("Request for mirroring configuration\n");
if (imask < 0 || imask > 0x3ffff) { /* 18 ports */
pr_error("Wrong ingress port mask 0x%x\n", imask);
*p_ret = -1;
return *p_ret;
}
if (emask < 0 || emask > 0x3ffff) { /* 18 ports */
pr_error("Wrong egress port mask 0x%x\n", emask);
*p_ret = -1;
return *p_ret;
}
if (enable == 1 && (dmask < 1 || dmask > 0x3ffff)) { /* 18 ports */
pr_error("Wrong destination port mask 0x%x\n", dmask);
*p_ret = -1;
return *p_ret;
}
rtu_enable_mirroring(0);
rtu_cfg_mirroring(enable, imask, emask, dmask);
rtu_enable_mirroring(enable);
return *p_ret;
}
int rtud_init_exports()
{
rtud_ch = minipc_server_create("rtud", 0);
......@@ -355,6 +392,7 @@ int rtud_init_exports()
MINIPC_EXP_FUNC(rtud_export_unrec, rtudexp_unrec);
MINIPC_EXP_FUNC(rtud_export_vlan_entry, rtudexp_vlan_entry);
MINIPC_EXP_FUNC(rtud_export_hp_mask, rtudexp_hp_mask);
MINIPC_EXP_FUNC(rtud_export_mirror, rtudexp_mirror);
return 0;
}
......
......@@ -133,4 +133,17 @@ struct minipc_pd rtud_export_hp_mask = {
},
};
/* Export of a function to configure port mirroring in rtu */
struct minipc_pd rtud_export_mirror = {
.name = "mirror",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* enable */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* ingress mask */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* egress mask */
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int), /* destination mask */
MINIPC_ARG_END,
},
};
#endif
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