From: Andrew Lunn The received RMU frame is expected to be addressed to the MAC address of the master interface. The sequence number should also match. Two formats codes are accepted. Add these basic sanity checks, and drop the frame is they are incorrect. To aid sequence number checking introduce the use of the DSA inband helpers and its data structures. Signed-off-by: Andrew Lunn Signed-off-by: Luke Howard --- drivers/net/dsa/mv88e6xxx/chip.c | 2 ++ drivers/net/dsa/mv88e6xxx/chip.h | 1 + drivers/net/dsa/mv88e6xxx/rmu.c | 42 ++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/rmu.h | 9 +++++++++ 4 files changed, 54 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index fe0d0eb8f0813..88cc2326ecc0c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -7462,6 +7462,8 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) if (err) goto out_g1_atu_prob_irq; + dsa_inband_init(&chip->rmu_inband, U8_MAX); + err = mv88e6xxx_register_switch(chip); if (err) goto out_g1_vtu_prob_irq; diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 76958b588a908..940ae698659fc 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -460,6 +460,7 @@ struct mv88e6xxx_chip { /* Remote Management Unit state. */ struct net_device *rmu_conduit; + struct dsa_inband rmu_inband; }; #define TCAM_MATCH_SIZE 96 diff --git a/drivers/net/dsa/mv88e6xxx/rmu.c b/drivers/net/dsa/mv88e6xxx/rmu.c index bae0ca6564f7a..49d67d512fb0f 100644 --- a/drivers/net/dsa/mv88e6xxx/rmu.c +++ b/drivers/net/dsa/mv88e6xxx/rmu.c @@ -53,4 +53,46 @@ void mv88e6xxx_rmu_frame2reg_handler(struct dsa_switch *ds, struct sk_buff *skb, u8 seqno) { + struct mv88e6xxx_rmu_header *rmu_header; + struct mv88e6xxx_chip *chip = ds->priv; + struct net_device *conduit; + unsigned char *ethhdr; + u8 expected_seqno; + + /* Check received destination MAC is the conduit MAC address */ + conduit = READ_ONCE(chip->rmu_conduit); + if (!conduit) + goto drop; + + ethhdr = skb_mac_header(skb); + if (!ether_addr_equal(conduit->dev_addr, ethhdr)) { + dev_dbg_ratelimited(ds->dev, "RMU: mismatched MAC address for request: rx %pM expecting %pM\n", + ethhdr, conduit->dev_addr); + goto drop; + } + + expected_seqno = dsa_inband_seqno(&chip->rmu_inband); + if (seqno != expected_seqno) { + dev_dbg_ratelimited(ds->dev, "RMU: mismatched seqno for request: rx %d expecting %d\n", + seqno, expected_seqno); + goto drop; + } + + if (skb->len < 4 + sizeof(*rmu_header)) { + dev_dbg_ratelimited(ds->dev, "RMU: response too short (%d bytes)\n", + skb->len); + dsa_inband_complete(&chip->rmu_inband, NULL, 0, -ETIMEDOUT); + goto drop; + } + + rmu_header = (struct mv88e6xxx_rmu_header *)(skb->data + 4); + if (rmu_header->format != MV88E6XXX_RMU_RESP_FORMAT_1 && + rmu_header->format != MV88E6XXX_RMU_RESP_FORMAT_2) { + dev_dbg_ratelimited(ds->dev, "RMU: invalid format: rx %d\n", + be16_to_cpu(rmu_header->format)); + goto drop; + } + +drop: + return; } diff --git a/drivers/net/dsa/mv88e6xxx/rmu.h b/drivers/net/dsa/mv88e6xxx/rmu.h index c60f32480e317..69cd3c2636f3d 100644 --- a/drivers/net/dsa/mv88e6xxx/rmu.h +++ b/drivers/net/dsa/mv88e6xxx/rmu.h @@ -9,6 +9,15 @@ #ifndef _MV88E6XXX_RMU_H_ #define _MV88E6XXX_RMU_H_ +#define MV88E6XXX_RMU_RESP_FORMAT_1 htons(0x0001) +#define MV88E6XXX_RMU_RESP_FORMAT_2 htons(0x0002) + +struct mv88e6xxx_rmu_header { + __be16 format; + __be16 prodnr; + __be16 code; +} __packed; + void mv88e6xxx_rmu_conduit_state_change(struct dsa_switch *ds, const struct net_device *conduit, bool operational); -- 2.43.0