mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 23:32:14 +00:00
The basic problem description is as follows:
Be there 3 switches in a daisy chain topology:
|
sw0p0 sw0p1 sw0p2 sw0p3 sw0p4
[ user ] [ user ] [ user ] [ dsa ] [ cpu ]
|
+---------+
|
sw1p0 sw1p1 sw1p2 sw1p3 sw1p4
[ user ] [ user ] [ user ] [ dsa ] [ dsa ]
|
+---------+
|
sw2p0 sw2p1 sw2p2 sw2p3 sw2p4
[ user ] [ user ] [ user ] [ user ] [ dsa ]
The CPU will not be able to ping through the user ports of the
bottom-most switch (like for example sw2p0), simply because tag_8021q
was not coded up for this scenario - it has always assumed DSA switch
trees with a single switch.
To add support for the topology above, we must admit that the RX VLAN of
sw2p0 must be added on some ports of switches 0 and 1 as well. This is
in fact a textbook example of thing that can use the cross-chip notifier
framework that DSA has set up in switch.c.
There is only one problem: core DSA (switch.c) is not able right now to
make the connection between a struct dsa_switch *ds and a struct
dsa_8021q_context *ctx. Right now, it is drivers who call into
tag_8021q.c and always provide a struct dsa_8021q_context *ctx pointer,
and tag_8021q.c calls them back with the .tag_8021q_vlan_{add,del}
methods.
But with cross-chip notifiers, it is possible for tag_8021q to call
drivers without drivers having ever asked for anything. A good example
is right above: when sw2p0 wants to set itself up for tag_8021q,
the .tag_8021q_vlan_add method needs to be called for switches 1 and 0,
so that they transport sw2p0's VLANs towards the CPU without dropping
them.
So instead of letting drivers manage the tag_8021q context, add a
tag_8021q_ctx pointer inside of struct dsa_switch, which will be
populated when dsa_tag_8021q_register() returns success.
The patch is fairly long-winded because we are partly reverting commit
5899ee367a
("net: dsa: tag_8021q: add a context structure") which made
the driver-facing tag_8021q API use "ctx" instead of "ds". Now that we
can access "ctx" directly from "ds", this is no longer needed.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
72 lines
1.8 KiB
C
72 lines
1.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0
|
|
* Copyright (c) 2019, Vladimir Oltean <olteanv@gmail.com>
|
|
*/
|
|
|
|
#ifndef _NET_DSA_8021Q_H
|
|
#define _NET_DSA_8021Q_H
|
|
|
|
#include <linux/refcount.h>
|
|
#include <linux/types.h>
|
|
|
|
struct dsa_switch;
|
|
struct sk_buff;
|
|
struct net_device;
|
|
struct dsa_8021q_context;
|
|
|
|
struct dsa_8021q_crosschip_link {
|
|
struct list_head list;
|
|
int port;
|
|
struct dsa_8021q_context *other_ctx;
|
|
int other_port;
|
|
refcount_t refcount;
|
|
};
|
|
|
|
struct dsa_8021q_ops {
|
|
int (*vlan_add)(struct dsa_switch *ds, int port, u16 vid, u16 flags);
|
|
int (*vlan_del)(struct dsa_switch *ds, int port, u16 vid);
|
|
};
|
|
|
|
struct dsa_8021q_context {
|
|
const struct dsa_8021q_ops *ops;
|
|
struct dsa_switch *ds;
|
|
struct list_head crosschip_links;
|
|
/* EtherType of RX VID, used for filtering on master interface */
|
|
__be16 proto;
|
|
};
|
|
|
|
int dsa_tag_8021q_register(struct dsa_switch *ds,
|
|
const struct dsa_8021q_ops *ops,
|
|
__be16 proto);
|
|
|
|
void dsa_tag_8021q_unregister(struct dsa_switch *ds);
|
|
|
|
int dsa_8021q_setup(struct dsa_switch *ds, bool enabled);
|
|
|
|
int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port,
|
|
struct dsa_switch *other_ds,
|
|
int other_port);
|
|
|
|
int dsa_8021q_crosschip_bridge_leave(struct dsa_switch *ds, int port,
|
|
struct dsa_switch *other_ds,
|
|
int other_port);
|
|
|
|
struct sk_buff *dsa_8021q_xmit(struct sk_buff *skb, struct net_device *netdev,
|
|
u16 tpid, u16 tci);
|
|
|
|
void dsa_8021q_rcv(struct sk_buff *skb, int *source_port, int *switch_id);
|
|
|
|
u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port);
|
|
|
|
u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port);
|
|
|
|
int dsa_8021q_rx_switch_id(u16 vid);
|
|
|
|
int dsa_8021q_rx_source_port(u16 vid);
|
|
|
|
bool vid_is_dsa_8021q_rxvlan(u16 vid);
|
|
|
|
bool vid_is_dsa_8021q_txvlan(u16 vid);
|
|
|
|
bool vid_is_dsa_8021q(u16 vid);
|
|
|
|
#endif /* _NET_DSA_8021Q_H */
|