net: dsa: mv88e6xxx: add VLAN support to FDB dump
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>
Thu, 13 Aug 2015 16:52:20 +0000 (12:52 -0400)
committerDavid S. Miller <davem@davemloft.net>
Fri, 14 Aug 2015 04:31:13 +0000 (21:31 -0700)
Add an helper function to read the next valid VLAN entry for a given
port. It is used in the VID to FID conversion function to retrieve the
forwarding database assigned to a given VLAN port.

Finally update the FDB getnext operation to iterate on the next valid
port VLAN when the end of the current database is reached.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx.c

index ecdd9dab37fd96c140052500582b6447a95c79f0..6c86bad25c61ffc24cf8d8e4884f15f02dc140b6 100644 (file)
@@ -1307,6 +1307,29 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, u16 vid,
        return 0;
 }
 
+static int _mv88e6xxx_port_vtu_getnext(struct dsa_switch *ds, int port, u16 vid,
+                                      struct mv88e6xxx_vtu_stu_entry *entry)
+{
+       int err;
+
+       do {
+               if (vid == 4095)
+                       return -ENOENT;
+
+               err = _mv88e6xxx_vtu_getnext(ds, vid, entry);
+               if (err)
+                       return err;
+
+               if (!entry->valid)
+                       return -ENOENT;
+
+               vid = entry->vid;
+       } while (entry->data[port] != GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED &&
+                entry->data[port] != GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED);
+
+       return 0;
+}
+
 int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid,
                           unsigned long *ports, unsigned long *untagged)
 {
@@ -1421,10 +1444,19 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
 static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       struct mv88e6xxx_vtu_stu_entry vlan;
+       int err;
 
        if (vid == 0)
                return ps->fid[port];
 
+       err = _mv88e6xxx_port_vtu_getnext(ds, port, vid - 1, &vlan);
+       if (err)
+               return err;
+
+       if (vlan.vid == vid)
+               return vlan.fid;
+
        return -ENOENT;
 }
 
@@ -1548,8 +1580,14 @@ int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
 
        do {
                if (is_broadcast_ether_addr(addr)) {
-                       ret = -ENOENT;
-                       goto unlock;
+                       struct mv88e6xxx_vtu_stu_entry vtu;
+
+                       ret = _mv88e6xxx_port_vtu_getnext(ds, port, *vid, &vtu);
+                       if (ret < 0)
+                               goto unlock;
+
+                       *vid = vtu.vid;
+                       fid = vtu.fid;
                }
 
                ret = _mv88e6xxx_atu_getnext(ds, fid, addr, &next);