Skip to content

Commit dfa6692

Browse files
committed
Merge branch 'Generic-adjustment-for-flow-dissector-in-DSA'
Vladimir Oltean says: ==================== Generic adjustment for flow dissector in DSA This is the v2 of a series initially submitted in May: https://www.spinics.net/lists/netdev/msg651866.html The end goal is to get rid of the unintuitive code for the flow dissector that currently exists in the taggers. It can all be replaced by a single, common function. Some background work needs to be done for that. Especially the ocelot driver poses some problems, since it has a different tag length between RX and TX, and I didn't want to make DSA aware of that, since I could instead make the tag lengths equal. Changes in v3: - Added an optimization (08/15) that makes the generic case not need to call the .flow_dissect function pointer. Basically .flow_dissect now currently only exists for sja1105. - Moved the .promisc_on_master property to the tagger structure. - Added the .tail_tag property to the tagger structure. - Disabled "suppresscc = all" from my .gitconfig. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 435be28 + 300fd57 commit dfa6692

File tree

19 files changed

+158
-135
lines changed

19 files changed

+158
-135
lines changed

drivers/net/dsa/ocelot/felix.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
439439
ocelot->vcap_is2_actions= felix->info->vcap_is2_actions;
440440
ocelot->vcap = felix->info->vcap;
441441
ocelot->ops = felix->info->ops;
442+
ocelot->inj_prefix = OCELOT_TAG_PREFIX_SHORT;
443+
ocelot->xtr_prefix = OCELOT_TAG_PREFIX_SHORT;
442444

443445
port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t),
444446
GFP_KERNEL);
@@ -509,7 +511,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
509511
return PTR_ERR(target);
510512
}
511513

512-
template = devm_kzalloc(ocelot->dev, OCELOT_TAG_LEN,
514+
template = devm_kzalloc(ocelot->dev, OCELOT_TOTAL_TAG_LEN,
513515
GFP_KERNEL);
514516
if (!template) {
515517
dev_err(ocelot->dev,
@@ -538,6 +540,28 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
538540
return 0;
539541
}
540542

543+
/* The CPU port module is connected to the Node Processor Interface (NPI). This
544+
* is the mode through which frames can be injected from and extracted to an
545+
* external CPU, over Ethernet.
546+
*/
547+
static void felix_npi_port_init(struct ocelot *ocelot, int port)
548+
{
549+
ocelot->npi = port;
550+
551+
ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
552+
QSYS_EXT_CPU_CFG_EXT_CPU_PORT(port),
553+
QSYS_EXT_CPU_CFG);
554+
555+
/* NPI port Injection/Extraction configuration */
556+
ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_XTR_HDR,
557+
ocelot->xtr_prefix);
558+
ocelot_fields_write(ocelot, port, SYS_PORT_MODE_INCL_INJ_HDR,
559+
ocelot->inj_prefix);
560+
561+
/* Disable transmission of pause frames */
562+
ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, 0);
563+
}
564+
541565
/* Hardware initialization done here so that we can allocate structures with
542566
* devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
543567
* us to allocate structures twice (leak memory) and map PCI memory twice
@@ -570,11 +594,8 @@ static int felix_setup(struct dsa_switch *ds)
570594
for (port = 0; port < ds->num_ports; port++) {
571595
ocelot_init_port(ocelot, port);
572596

573-
/* Bring up the CPU port module and configure the NPI port */
574597
if (dsa_is_cpu_port(ds, port))
575-
ocelot_configure_cpu(ocelot, port,
576-
OCELOT_TAG_PREFIX_NONE,
577-
OCELOT_TAG_PREFIX_LONG);
598+
felix_npi_port_init(ocelot, port);
578599

579600
/* Set the default QoS Classification based on PCP and DEI
580601
* bits of vlan tag.

drivers/net/dsa/ocelot/felix_vsc9959.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,8 @@ static void vsc9959_xmit_template_populate(struct ocelot *ocelot, int port)
11551155
struct ocelot_port *ocelot_port = ocelot->ports[port];
11561156
u8 *template = ocelot_port->xmit_template;
11571157
u64 bypass, dest, src;
1158+
__be32 *prefix;
1159+
u8 *injection;
11581160

11591161
/* Set the source port as the CPU port module and not the
11601162
* NPI port
@@ -1163,9 +1165,14 @@ static void vsc9959_xmit_template_populate(struct ocelot *ocelot, int port)
11631165
dest = BIT(port);
11641166
bypass = true;
11651167

1166-
packing(template, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
1167-
packing(template, &dest, 68, 56, OCELOT_TAG_LEN, PACK, 0);
1168-
packing(template, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0);
1168+
injection = template + OCELOT_SHORT_PREFIX_LEN;
1169+
prefix = (__be32 *)template;
1170+
1171+
packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
1172+
packing(injection, &dest, 68, 56, OCELOT_TAG_LEN, PACK, 0);
1173+
packing(injection, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0);
1174+
1175+
*prefix = cpu_to_be32(0x8880000a);
11691176
}
11701177

11711178
static const struct felix_info felix_info_vsc9959 = {

drivers/net/dsa/ocelot/seville_vsc9953.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,8 @@ static void vsc9953_xmit_template_populate(struct ocelot *ocelot, int port)
10031003
struct ocelot_port *ocelot_port = ocelot->ports[port];
10041004
u8 *template = ocelot_port->xmit_template;
10051005
u64 bypass, dest, src;
1006+
__be32 *prefix;
1007+
u8 *injection;
10061008

10071009
/* Set the source port as the CPU port module and not the
10081010
* NPI port
@@ -1011,9 +1013,14 @@ static void vsc9953_xmit_template_populate(struct ocelot *ocelot, int port)
10111013
dest = BIT(port);
10121014
bypass = true;
10131015

1014-
packing(template, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
1015-
packing(template, &dest, 67, 57, OCELOT_TAG_LEN, PACK, 0);
1016-
packing(template, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0);
1016+
injection = template + OCELOT_SHORT_PREFIX_LEN;
1017+
prefix = (__be32 *)template;
1018+
1019+
packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
1020+
packing(injection, &dest, 67, 57, OCELOT_TAG_LEN, PACK, 0);
1021+
packing(injection, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0);
1022+
1023+
*prefix = cpu_to_be32(0x88800005);
10171024
}
10181025

10191026
static const struct felix_info seville_info_vsc9953 = {

drivers/net/ethernet/mscc/ocelot.c

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,22 +1346,14 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
13461346
}
13471347
EXPORT_SYMBOL(ocelot_init_port);
13481348

1349-
/* Configure and enable the CPU port module, which is a set of queues.
1350-
* If @npi contains a valid port index, the CPU port module is connected
1351-
* to the Node Processor Interface (NPI). This is the mode through which
1352-
* frames can be injected from and extracted to an external CPU,
1353-
* over Ethernet.
1349+
/* Configure and enable the CPU port module, which is a set of queues
1350+
* accessible through register MMIO, frame DMA or Ethernet (in case
1351+
* NPI mode is used).
13541352
*/
1355-
void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
1356-
enum ocelot_tag_prefix injection,
1357-
enum ocelot_tag_prefix extraction)
1353+
static void ocelot_cpu_port_init(struct ocelot *ocelot)
13581354
{
13591355
int cpu = ocelot->num_phys_ports;
13601356

1361-
ocelot->npi = npi;
1362-
ocelot->inj_prefix = injection;
1363-
ocelot->xtr_prefix = extraction;
1364-
13651357
/* The unicast destination PGID for the CPU port module is unused */
13661358
ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
13671359
/* Instead set up a multicast destination PGID for traffic copied to
@@ -1373,39 +1365,20 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
13731365
ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
13741366
ANA_PORT_PORT_CFG, cpu);
13751367

1376-
if (npi >= 0 && npi < ocelot->num_phys_ports) {
1377-
ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
1378-
QSYS_EXT_CPU_CFG_EXT_CPU_PORT(npi),
1379-
QSYS_EXT_CPU_CFG);
1380-
1381-
/* Enable NPI port */
1382-
ocelot_fields_write(ocelot, npi,
1383-
QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
1384-
/* NPI port Injection/Extraction configuration */
1385-
ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_XTR_HDR,
1386-
extraction);
1387-
ocelot_fields_write(ocelot, npi, SYS_PORT_MODE_INCL_INJ_HDR,
1388-
injection);
1389-
1390-
/* Disable transmission of pause frames */
1391-
ocelot_fields_write(ocelot, npi, SYS_PAUSE_CFG_PAUSE_ENA, 0);
1392-
}
1393-
13941368
/* Enable CPU port module */
13951369
ocelot_fields_write(ocelot, cpu, QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
13961370
/* CPU port Injection/Extraction configuration */
13971371
ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_XTR_HDR,
1398-
extraction);
1372+
ocelot->xtr_prefix);
13991373
ocelot_fields_write(ocelot, cpu, SYS_PORT_MODE_INCL_INJ_HDR,
1400-
injection);
1374+
ocelot->inj_prefix);
14011375

14021376
/* Configure the CPU port to be VLAN aware */
14031377
ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
14041378
ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
14051379
ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
14061380
ANA_PORT_VLAN_CFG, cpu);
14071381
}
1408-
EXPORT_SYMBOL(ocelot_configure_cpu);
14091382

14101383
int ocelot_init(struct ocelot *ocelot)
14111384
{
@@ -1445,6 +1418,7 @@ int ocelot_init(struct ocelot *ocelot)
14451418
ocelot_mact_init(ocelot);
14461419
ocelot_vlan_init(ocelot);
14471420
ocelot_vcap_init(ocelot);
1421+
ocelot_cpu_port_init(ocelot);
14481422

14491423
for (port = 0; port < ocelot->num_phys_ports; port++) {
14501424
/* Clear all counters (5 groups) */

drivers/net/ethernet/mscc/ocelot_vsc7514.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -930,10 +930,6 @@ static int mscc_ocelot_init_ports(struct platform_device *pdev,
930930
if (!ocelot->ports)
931931
return -ENOMEM;
932932

933-
/* No NPI port */
934-
ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
935-
OCELOT_TAG_PREFIX_NONE);
936-
937933
for_each_available_child_of_node(ports, portnp) {
938934
struct ocelot_port_private *priv;
939935
struct ocelot_port *ocelot_port;
@@ -1120,6 +1116,9 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
11201116
ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
11211117
ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
11221118
ocelot->vcap = vsc7514_vcap_props;
1119+
ocelot->inj_prefix = OCELOT_TAG_PREFIX_NONE;
1120+
ocelot->xtr_prefix = OCELOT_TAG_PREFIX_NONE;
1121+
ocelot->npi = -1;
11231122

11241123
err = ocelot_init(ocelot);
11251124
if (err)

include/net/dsa.h

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ struct dsa_device_ops {
7474
struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
7575
struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
7676
struct packet_type *pt);
77-
int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
78-
int *offset);
77+
void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
78+
int *offset);
7979
/* Used to determine which traffic should match the DSA filter in
8080
* eth_type_trans, and which, if any, should bypass it and be processed
8181
* as regular on the master net device.
@@ -84,6 +84,13 @@ struct dsa_device_ops {
8484
unsigned int overhead;
8585
const char *name;
8686
enum dsa_tag_protocol proto;
87+
/* Some tagging protocols either mangle or shift the destination MAC
88+
* address, in which case the DSA master would drop packets on ingress
89+
* if what it understands out of the destination MAC address is not in
90+
* its RX filter.
91+
*/
92+
bool promisc_on_master;
93+
bool tail_tag;
8794
};
8895

8996
/* This structure defines the control interfaces that are overlayed by the
@@ -705,6 +712,32 @@ static inline bool dsa_can_decode(const struct sk_buff *skb,
705712
return false;
706713
}
707714

715+
/* All DSA tags that push the EtherType to the right (basically all except tail
716+
* tags, which don't break dissection) can be treated the same from the
717+
* perspective of the flow dissector.
718+
*
719+
* We need to return:
720+
* - offset: the (B - A) difference between:
721+
* A. the position of the real EtherType and
722+
* B. the current skb->data (aka ETH_HLEN bytes into the frame, aka 2 bytes
723+
* after the normal EtherType was supposed to be)
724+
* The offset in bytes is exactly equal to the tagger overhead (and half of
725+
* that, in __be16 shorts).
726+
*
727+
* - proto: the value of the real EtherType.
728+
*/
729+
static inline void dsa_tag_generic_flow_dissect(const struct sk_buff *skb,
730+
__be16 *proto, int *offset)
731+
{
732+
#if IS_ENABLED(CONFIG_NET_DSA)
733+
const struct dsa_device_ops *ops = skb->dev->dsa_ptr->tag_ops;
734+
int tag_len = ops->overhead;
735+
736+
*offset = tag_len;
737+
*proto = ((__be16 *)skb->data)[(tag_len / 2) - 1];
738+
#endif
739+
}
740+
708741
#if IS_ENABLED(CONFIG_NET_DSA)
709742
static inline int __dsa_netdevice_ops_check(struct net_device *dev)
710743
{

include/soc/mscc/ocelot.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#define OCELOT_TAG_LEN 16
102102
#define OCELOT_SHORT_PREFIX_LEN 4
103103
#define OCELOT_LONG_PREFIX_LEN 16
104+
#define OCELOT_TOTAL_TAG_LEN (OCELOT_SHORT_PREFIX_LEN + OCELOT_TAG_LEN)
104105

105106
#define OCELOT_SPEED_2500 0
106107
#define OCELOT_SPEED_1000 1
@@ -672,9 +673,6 @@ void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
672673
int ocelot_regfields_init(struct ocelot *ocelot,
673674
const struct reg_field *const regfields);
674675
struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res);
675-
void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
676-
enum ocelot_tag_prefix injection,
677-
enum ocelot_tag_prefix extraction);
678676
int ocelot_init(struct ocelot *ocelot);
679677
void ocelot_deinit(struct ocelot *ocelot);
680678
void ocelot_init_port(struct ocelot *ocelot, int port);

net/core/flow_dissector.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -932,8 +932,14 @@ bool __skb_flow_dissect(const struct net *net,
932932
int offset = 0;
933933

934934
ops = skb->dev->dsa_ptr->tag_ops;
935-
if (ops->flow_dissect &&
936-
!ops->flow_dissect(skb, &proto, &offset)) {
935+
/* Tail taggers don't break flow dissection */
936+
if (!ops->tail_tag) {
937+
if (ops->flow_dissect)
938+
ops->flow_dissect(skb, &proto, &offset);
939+
else
940+
dsa_tag_generic_flow_dissect(skb,
941+
&proto,
942+
&offset);
937943
hlen -= offset;
938944
nhoff += offset;
939945
}

net/dsa/master.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,18 @@ static void dsa_netdev_ops_set(struct net_device *dev,
259259
dev->dsa_ptr->netdev_ops = ops;
260260
}
261261

262+
static void dsa_master_set_promiscuity(struct net_device *dev, int inc)
263+
{
264+
const struct dsa_device_ops *ops = dev->dsa_ptr->tag_ops;
265+
266+
if (!ops->promisc_on_master)
267+
return;
268+
269+
rtnl_lock();
270+
dev_set_promiscuity(dev, inc);
271+
rtnl_unlock();
272+
}
273+
262274
static ssize_t tagging_show(struct device *d, struct device_attribute *attr,
263275
char *buf)
264276
{
@@ -314,9 +326,12 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
314326
dev->dsa_ptr = cpu_dp;
315327
lockdep_set_class(&dev->addr_list_lock,
316328
&dsa_master_addr_list_lock_key);
329+
330+
dsa_master_set_promiscuity(dev, 1);
331+
317332
ret = dsa_master_ethtool_setup(dev);
318333
if (ret)
319-
return ret;
334+
goto out_err_reset_promisc;
320335

321336
dsa_netdev_ops_set(dev, &dsa_netdev_ops);
322337

@@ -329,6 +344,8 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
329344
out_err_ndo_teardown:
330345
dsa_netdev_ops_set(dev, NULL);
331346
dsa_master_ethtool_teardown(dev);
347+
out_err_reset_promisc:
348+
dsa_master_set_promiscuity(dev, -1);
332349
return ret;
333350
}
334351

@@ -338,6 +355,7 @@ void dsa_master_teardown(struct net_device *dev)
338355
dsa_netdev_ops_set(dev, NULL);
339356
dsa_master_ethtool_teardown(dev);
340357
dsa_master_reset_mtu(dev);
358+
dsa_master_set_promiscuity(dev, -1);
341359

342360
dev->dsa_ptr = NULL;
343361

0 commit comments

Comments
 (0)