mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2024-06-26 09:37:29 +02:00
kernel: add mv88e61xx switch port-mirroring support
Compile & run tested on mvebu Signed-off-by: Deng Qingfang <dengqf6@mail2.sysu.edu.cn>
This commit is contained in:
parent
b88ce25e81
commit
18501889f6
|
@ -454,6 +454,86 @@ static int mvsw61xx_set_enable_vlan(struct switch_dev *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mvsw61xx_get_mirror_rx_enable(struct switch_dev *dev,
|
||||||
|
const struct switch_attr *attr, struct switch_val *val)
|
||||||
|
{
|
||||||
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
|
||||||
|
val->value.i = state->mirror_rx;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mvsw61xx_set_mirror_rx_enable(struct switch_dev *dev,
|
||||||
|
const struct switch_attr *attr, struct switch_val *val)
|
||||||
|
{
|
||||||
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
|
||||||
|
state->mirror_rx = val->value.i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mvsw61xx_get_mirror_tx_enable(struct switch_dev *dev,
|
||||||
|
const struct switch_attr *attr, struct switch_val *val)
|
||||||
|
{
|
||||||
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
|
||||||
|
val->value.i = state->mirror_tx;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mvsw61xx_set_mirror_tx_enable(struct switch_dev *dev,
|
||||||
|
const struct switch_attr *attr, struct switch_val *val)
|
||||||
|
{
|
||||||
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
|
||||||
|
state->mirror_tx = val->value.i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mvsw61xx_get_mirror_monitor_port(struct switch_dev *dev,
|
||||||
|
const struct switch_attr *attr, struct switch_val *val)
|
||||||
|
{
|
||||||
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
|
||||||
|
val->value.i = state->monitor_port;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mvsw61xx_set_mirror_monitor_port(struct switch_dev *dev,
|
||||||
|
const struct switch_attr *attr, struct switch_val *val)
|
||||||
|
{
|
||||||
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
|
||||||
|
state->monitor_port = val->value.i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mvsw61xx_get_mirror_source_port(struct switch_dev *dev,
|
||||||
|
const struct switch_attr *attr, struct switch_val *val)
|
||||||
|
{
|
||||||
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
|
||||||
|
val->value.i = state->source_port;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mvsw61xx_set_mirror_source_port(struct switch_dev *dev,
|
||||||
|
const struct switch_attr *attr, struct switch_val *val)
|
||||||
|
{
|
||||||
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
|
||||||
|
state->source_port = val->value.i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mvsw61xx_vtu_program(struct switch_dev *dev)
|
static int mvsw61xx_vtu_program(struct switch_dev *dev)
|
||||||
{
|
{
|
||||||
struct mvsw61xx_state *state = get_state(dev);
|
struct mvsw61xx_state *state = get_state(dev);
|
||||||
|
@ -604,6 +684,40 @@ static int mvsw61xx_update_state(struct switch_dev *dev)
|
||||||
|
|
||||||
mvsw61xx_vtu_program(dev);
|
mvsw61xx_vtu_program(dev);
|
||||||
|
|
||||||
|
/* port mirroring */
|
||||||
|
/* reset all mirror registers */
|
||||||
|
for (i = 0; i < dev->ports; i++) {
|
||||||
|
reg = sr16(dev, MV_PORTREG(CONTROL2, i));
|
||||||
|
reg &= ~(MV_MIRROR_RX_SRC_MASK | MV_MIRROR_TX_SRC_MASK);
|
||||||
|
sw16(dev, MV_PORTREG(CONTROL2, i), reg);
|
||||||
|
}
|
||||||
|
reg = sr16(dev, MV_GLOBALREG(MONITOR_CTRL));
|
||||||
|
reg |= MV_MIRROR_RX_DEST_MASK | MV_MIRROR_TX_DEST_MASK;
|
||||||
|
sw16(dev, MV_GLOBALREG(MONITOR_CTRL), reg);
|
||||||
|
|
||||||
|
/* now enable mirroring if necessary */
|
||||||
|
if (state->mirror_rx) {
|
||||||
|
/* set ingress monitor source */
|
||||||
|
reg = sr16(dev, MV_PORTREG(CONTROL2, state->source_port)) & ~MV_MIRROR_RX_SRC_MASK;
|
||||||
|
reg |= state->mirror_rx << MV_MIRROR_RX_SRC_SHIFT;
|
||||||
|
sw16(dev, MV_PORTREG(CONTROL2, state->source_port), reg);
|
||||||
|
/* set ingress monitor destination */
|
||||||
|
reg = sr16(dev, MV_GLOBALREG(MONITOR_CTRL)) & ~MV_MIRROR_RX_DEST_MASK;
|
||||||
|
reg |= state->monitor_port << MV_MIRROR_RX_DEST_SHIFT;
|
||||||
|
sw16(dev, MV_GLOBALREG(MONITOR_CTRL), reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->mirror_tx) {
|
||||||
|
/* set egress monitor source */
|
||||||
|
reg = sr16(dev, MV_PORTREG(CONTROL2, state->source_port)) & ~MV_MIRROR_TX_SRC_MASK;
|
||||||
|
reg |= state->mirror_tx << MV_MIRROR_TX_SRC_SHIFT;
|
||||||
|
sw16(dev, MV_PORTREG(CONTROL2, state->source_port), reg);
|
||||||
|
/* set egress monitor destination */
|
||||||
|
reg = sr16(dev, MV_GLOBALREG(MONITOR_CTRL)) & ~MV_MIRROR_TX_DEST_MASK;
|
||||||
|
reg |= state->monitor_port << MV_MIRROR_TX_DEST_SHIFT;
|
||||||
|
sw16(dev, MV_GLOBALREG(MONITOR_CTRL), reg);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,6 +807,11 @@ static int _mvsw61xx_reset(struct switch_dev *dev, bool full)
|
||||||
|
|
||||||
state->vlan_enabled = 0;
|
state->vlan_enabled = 0;
|
||||||
|
|
||||||
|
state->mirror_rx = false;
|
||||||
|
state->mirror_tx = false;
|
||||||
|
state->source_port = 0;
|
||||||
|
state->monitor_port = 0;
|
||||||
|
|
||||||
mvsw61xx_update_state(dev);
|
mvsw61xx_update_state(dev);
|
||||||
|
|
||||||
/* Re-enable ports */
|
/* Re-enable ports */
|
||||||
|
@ -710,10 +829,6 @@ static int mvsw61xx_reset(struct switch_dev *dev)
|
||||||
return _mvsw61xx_reset(dev, false);
|
return _mvsw61xx_reset(dev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
|
||||||
MVSW61XX_ENABLE_VLAN,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MVSW61XX_VLAN_PORT_BASED,
|
MVSW61XX_VLAN_PORT_BASED,
|
||||||
MVSW61XX_VLAN_ID,
|
MVSW61XX_VLAN_ID,
|
||||||
|
@ -725,14 +840,45 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct switch_attr mvsw61xx_global[] = {
|
static const struct switch_attr mvsw61xx_global[] = {
|
||||||
[MVSW61XX_ENABLE_VLAN] = {
|
{
|
||||||
.id = MVSW61XX_ENABLE_VLAN,
|
|
||||||
.type = SWITCH_TYPE_INT,
|
.type = SWITCH_TYPE_INT,
|
||||||
.name = "enable_vlan",
|
.name = "enable_vlan",
|
||||||
.description = "Enable 802.1q VLAN support",
|
.description = "Enable 802.1q VLAN support",
|
||||||
.get = mvsw61xx_get_enable_vlan,
|
.get = mvsw61xx_get_enable_vlan,
|
||||||
.set = mvsw61xx_set_enable_vlan,
|
.set = mvsw61xx_set_enable_vlan,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.type = SWITCH_TYPE_INT,
|
||||||
|
.name = "enable_mirror_rx",
|
||||||
|
.description = "Enable mirroring of RX packets",
|
||||||
|
.set = mvsw61xx_set_mirror_rx_enable,
|
||||||
|
.get = mvsw61xx_get_mirror_rx_enable,
|
||||||
|
.max = 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = SWITCH_TYPE_INT,
|
||||||
|
.name = "enable_mirror_tx",
|
||||||
|
.description = "Enable mirroring of TX packets",
|
||||||
|
.set = mvsw61xx_set_mirror_tx_enable,
|
||||||
|
.get = mvsw61xx_get_mirror_tx_enable,
|
||||||
|
.max = 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = SWITCH_TYPE_INT,
|
||||||
|
.name = "mirror_monitor_port",
|
||||||
|
.description = "Mirror monitor port",
|
||||||
|
.set = mvsw61xx_set_mirror_monitor_port,
|
||||||
|
.get = mvsw61xx_get_mirror_monitor_port,
|
||||||
|
.max = MV_PORTS - 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = SWITCH_TYPE_INT,
|
||||||
|
.name = "mirror_source_port",
|
||||||
|
.description = "Mirror source port",
|
||||||
|
.set = mvsw61xx_set_mirror_source_port,
|
||||||
|
.get = mvsw61xx_get_mirror_source_port,
|
||||||
|
.max = MV_PORTS - 1
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct switch_attr mvsw61xx_vlan[] = {
|
static const struct switch_attr mvsw61xx_vlan[] = {
|
||||||
|
|
|
@ -165,6 +165,7 @@ enum {
|
||||||
MV_GLOBAL_VTU_DATA1 = 0x07,
|
MV_GLOBAL_VTU_DATA1 = 0x07,
|
||||||
MV_GLOBAL_VTU_DATA2 = 0x08,
|
MV_GLOBAL_VTU_DATA2 = 0x08,
|
||||||
MV_GLOBAL_VTU_DATA3 = 0x09,
|
MV_GLOBAL_VTU_DATA3 = 0x09,
|
||||||
|
MV_GLOBAL_MONITOR_CTRL = 0x1a,
|
||||||
MV_GLOBAL_CONTROL2 = 0x1c,
|
MV_GLOBAL_CONTROL2 = 0x1c,
|
||||||
};
|
};
|
||||||
#define MV_GLOBALREG(_type) MV_SWITCH_GLOBAL, MV_GLOBAL_##_type
|
#define MV_GLOBALREG(_type) MV_SWITCH_GLOBAL, MV_GLOBAL_##_type
|
||||||
|
@ -242,6 +243,16 @@ enum {
|
||||||
#define MV_FDB_HI_SHIFT 4
|
#define MV_FDB_HI_SHIFT 4
|
||||||
#define MV_FDB_LO_SHIFT 12
|
#define MV_FDB_LO_SHIFT 12
|
||||||
|
|
||||||
|
#define MV_MIRROR_RX_DEST_MASK 0xf000
|
||||||
|
#define MV_MIRROR_TX_DEST_MASK 0x0f00
|
||||||
|
#define MV_MIRROR_RX_DEST_SHIFT 12
|
||||||
|
#define MV_MIRROR_TX_DEST_SHIFT 8
|
||||||
|
|
||||||
|
#define MV_MIRROR_RX_SRC_SHIFT 4
|
||||||
|
#define MV_MIRROR_RX_SRC_MASK (1 << MV_MIRROR_RX_SRC_SHIFT)
|
||||||
|
#define MV_MIRROR_TX_SRC_SHIFT 5
|
||||||
|
#define MV_MIRROR_TX_SRC_MASK (1 << MV_MIRROR_TX_SRC_SHIFT)
|
||||||
|
|
||||||
/* Marvell Specific PHY register */
|
/* Marvell Specific PHY register */
|
||||||
#define MII_MV_SPEC_CTRL 16
|
#define MII_MV_SPEC_CTRL 16
|
||||||
enum {
|
enum {
|
||||||
|
@ -284,6 +295,12 @@ struct mvsw61xx_state {
|
||||||
u32 port_sstate;
|
u32 port_sstate;
|
||||||
} vlans[MV_VLANS];
|
} vlans[MV_VLANS];
|
||||||
|
|
||||||
|
/* mirroring */
|
||||||
|
bool mirror_rx;
|
||||||
|
bool mirror_tx;
|
||||||
|
int source_port;
|
||||||
|
int monitor_port;
|
||||||
|
|
||||||
char buf[128];
|
char buf[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user