* [PATCH v2 net 0/5] Ocelot VCAP fixes
@ 2022-05-04 23:54 Vladimir Oltean
2022-05-04 23:54 ` [PATCH v2 net 1/5] net: mscc: ocelot: mark traps with a bool instead of keeping them in a list Vladimir Oltean
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Vladimir Oltean @ 2022-05-04 23:54 UTC (permalink / raw)
To: netdev
Cc: Jakub Kicinski, David S. Miller, Paolo Abeni, Eric Dumazet,
Florian Fainelli, Vivien Didelot, Andrew Lunn, Vladimir Oltean,
Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver, Xiaoliang Yang,
Colin Foster
Changes in v2:
fix the NPDs and UAFs caused by filter->trap_list in a more robust way
that actually does not introduce bugs of its own (1/5)
This series fixes issues found while running
tools/testing/selftests/net/forwarding/tc_actions.sh on the ocelot
switch:
- NULL pointer dereference when failing to offload a filter
- NULL pointer dereference after deleting a trap
- filters still having effect after being deleted
- dropped packets still being seen by software
- statistics counters showing double the amount of hits
- statistics counters showing inexistent hits
- invalid configurations not rejected
Vladimir Oltean (5):
net: mscc: ocelot: mark traps with a bool instead of keeping them in a
list
net: mscc: ocelot: fix last VCAP IS1/IS2 filter persisting in hardware
when deleted
net: mscc: ocelot: fix VCAP IS2 filters matching on both lookups
net: mscc: ocelot: restrict tc-trap actions to VCAP IS2 lookup 0
net: mscc: ocelot: avoid corrupting hardware counters when moving VCAP
filters
drivers/net/dsa/ocelot/felix.c | 7 ++++++-
drivers/net/ethernet/mscc/ocelot.c | 11 +++--------
drivers/net/ethernet/mscc/ocelot_flower.c | 9 ++++-----
drivers/net/ethernet/mscc/ocelot_vcap.c | 9 ++++++++-
include/soc/mscc/ocelot_vcap.h | 2 +-
5 files changed, 22 insertions(+), 16 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 net 1/5] net: mscc: ocelot: mark traps with a bool instead of keeping them in a list
2022-05-04 23:54 [PATCH v2 net 0/5] Ocelot VCAP fixes Vladimir Oltean
@ 2022-05-04 23:54 ` Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 2/5] net: mscc: ocelot: fix last VCAP IS1/IS2 filter persisting in hardware when deleted Vladimir Oltean
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Oltean @ 2022-05-04 23:54 UTC (permalink / raw)
To: netdev
Cc: Jakub Kicinski, David S. Miller, Paolo Abeni, Eric Dumazet,
Florian Fainelli, Vivien Didelot, Andrew Lunn, Vladimir Oltean,
Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver, Xiaoliang Yang,
Colin Foster
Since the blamed commit, VCAP filters can appear on more than one list.
If their action is "trap", they are chained on ocelot->traps via
filter->trap_list. This is in addition to their normal placement on the
VCAP block->rules list head.
Therefore, when we free a VCAP filter, we must remove it from all lists
it is a member of, including ocelot->traps.
There are at least 2 bugs which are direct consequences of this design
decision.
First is the incorrect usage of list_empty(), meant to denote whether
"filter" is chained into ocelot->traps via filter->trap_list.
This does not do the correct thing, because list_empty() checks whether
"head->next == head", but in our case, head->next == head->prev == NULL.
So we dereference NULL pointers and die when we call list_del().
Second is the fact that not all places that should remove the filter
from ocelot->traps do so. One example is ocelot_vcap_block_remove_filter(),
which is where we have the main kfree(filter). By keeping freed filters
in ocelot->traps we end up in a use-after-free in
felix_update_trapping_destinations().
Attempting to fix all the buggy patterns is a whack-a-mole game which
makes the driver unmaintainable. Actually this is what the previous
patch version attempted to do:
https://patchwork.kernel.org/project/netdevbpf/patch/20220503115728.834457-3-vladimir.oltean@nxp.com/
but it introduced another set of bugs, because there are other places in
which create VCAP filters, not just ocelot_vcap_filter_create():
- ocelot_trap_add()
- felix_tag_8021q_vlan_add_rx()
- felix_tag_8021q_vlan_add_tx()
Relying on the convention that all those code paths must call
INIT_LIST_HEAD(&filter->trap_list) is not going to scale.
So let's do what should have been done in the first place and keep a
bool in struct ocelot_vcap_filter which denotes whether we are looking
at a trapping rule or not. Iterating now happens over the main VCAP IS2
block->rules. The advantage is that we no longer risk having stale
references to a freed filter, since it is only present in that list.
Fixes: e42bd4ed09aa ("net: mscc: ocelot: keep traps in a list")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v2: patch is new, replaces previous patches 1/6 and 2/6
drivers/net/dsa/ocelot/felix.c | 7 ++++++-
drivers/net/ethernet/mscc/ocelot.c | 11 +++--------
drivers/net/ethernet/mscc/ocelot_flower.c | 4 +---
include/soc/mscc/ocelot_vcap.h | 2 +-
4 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 33cb124ca912..a1b6c2df96c2 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -403,6 +403,7 @@ static int felix_update_trapping_destinations(struct dsa_switch *ds,
{
struct ocelot *ocelot = ds->priv;
struct felix *felix = ocelot_to_felix(ocelot);
+ struct ocelot_vcap_block *block_vcap_is2;
struct ocelot_vcap_filter *trap;
enum ocelot_mask_mode mask_mode;
unsigned long port_mask;
@@ -422,9 +423,13 @@ static int felix_update_trapping_destinations(struct dsa_switch *ds,
/* We are sure that "cpu" was found, otherwise
* dsa_tree_setup_default_cpu() would have failed earlier.
*/
+ block_vcap_is2 = &ocelot->block[VCAP_IS2];
/* Make sure all traps are set up for that destination */
- list_for_each_entry(trap, &ocelot->traps, trap_list) {
+ list_for_each_entry(trap, &block_vcap_is2->rules, list) {
+ if (!trap->is_trap)
+ continue;
+
/* Figure out the current trapping destination */
if (using_tag_8021q) {
/* Redirect to the tag_8021q CPU port. If timestamps
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 0825a92599a5..880dee767d96 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1622,7 +1622,7 @@ int ocelot_trap_add(struct ocelot *ocelot, int port,
trap->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
trap->action.port_mask = 0;
trap->take_ts = take_ts;
- list_add_tail(&trap->trap_list, &ocelot->traps);
+ trap->is_trap = true;
new = true;
}
@@ -1634,10 +1634,8 @@ int ocelot_trap_add(struct ocelot *ocelot, int port,
err = ocelot_vcap_filter_replace(ocelot, trap);
if (err) {
trap->ingress_port_mask &= ~BIT(port);
- if (!trap->ingress_port_mask) {
- list_del(&trap->trap_list);
+ if (!trap->ingress_port_mask)
kfree(trap);
- }
return err;
}
@@ -1657,11 +1655,8 @@ int ocelot_trap_del(struct ocelot *ocelot, int port, unsigned long cookie)
return 0;
trap->ingress_port_mask &= ~BIT(port);
- if (!trap->ingress_port_mask) {
- list_del(&trap->trap_list);
-
+ if (!trap->ingress_port_mask)
return ocelot_vcap_filter_del(ocelot, trap);
- }
return ocelot_vcap_filter_replace(ocelot, trap);
}
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index 03b5e59d033e..a9b26b3002be 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -295,7 +295,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
filter->action.cpu_copy_ena = true;
filter->action.cpu_qu_num = 0;
filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
- list_add_tail(&filter->trap_list, &ocelot->traps);
+ filter->is_trap = true;
break;
case FLOW_ACTION_POLICE:
if (filter->block_id == PSFP_BLOCK_ID) {
@@ -878,8 +878,6 @@ int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
if (ret) {
- if (!list_empty(&filter->trap_list))
- list_del(&filter->trap_list);
kfree(filter);
return ret;
}
diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h
index 7b2bf9b1fe69..de26c992f821 100644
--- a/include/soc/mscc/ocelot_vcap.h
+++ b/include/soc/mscc/ocelot_vcap.h
@@ -681,7 +681,6 @@ struct ocelot_vcap_id {
struct ocelot_vcap_filter {
struct list_head list;
- struct list_head trap_list;
enum ocelot_vcap_filter_type type;
int block_id;
@@ -695,6 +694,7 @@ struct ocelot_vcap_filter {
struct ocelot_vcap_stats stats;
/* For VCAP IS1 and IS2 */
bool take_ts;
+ bool is_trap;
unsigned long ingress_port_mask;
/* For VCAP ES0 */
struct ocelot_vcap_port ingress_port;
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 net 2/5] net: mscc: ocelot: fix last VCAP IS1/IS2 filter persisting in hardware when deleted
2022-05-04 23:54 [PATCH v2 net 0/5] Ocelot VCAP fixes Vladimir Oltean
2022-05-04 23:54 ` [PATCH v2 net 1/5] net: mscc: ocelot: mark traps with a bool instead of keeping them in a list Vladimir Oltean
@ 2022-05-04 23:55 ` Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 3/5] net: mscc: ocelot: fix VCAP IS2 filters matching on both lookups Vladimir Oltean
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Oltean @ 2022-05-04 23:55 UTC (permalink / raw)
To: netdev
Cc: Jakub Kicinski, David S. Miller, Paolo Abeni, Eric Dumazet,
Florian Fainelli, Vivien Didelot, Andrew Lunn, Vladimir Oltean,
Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver, Xiaoliang Yang,
Colin Foster
ocelot_vcap_filter_del() works by moving the next filters over the
current one, and then deleting the last filter by calling vcap_entry_set()
with a del_filter which was specially created by memsetting its memory
to zeroes. vcap_entry_set() then programs this to the TCAM and action
RAM via the cache registers.
The problem is that vcap_entry_set() is a dispatch function which looks
at del_filter->block_id. But since del_filter is zeroized memory, the
block_id is 0, or otherwise said, VCAP_ES0. So practically, what we do
is delete the entry at the same TCAM index from VCAP ES0 instead of IS1
or IS2.
The code was not always like this. vcap_entry_set() used to simply be
is2_entry_set(), and then, the logic used to work.
Restore the functionality by populating the block_id of the del_filter
based on the VCAP block of the filter that we're deleting. This makes
vcap_entry_set() know what to do.
Fixes: 1397a2eb52e2 ("net: mscc: ocelot: create TCAM skeleton from tc filter chains")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v2: none
drivers/net/ethernet/mscc/ocelot_vcap.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c
index 1e74bdb215ec..c08cfcf4c2a2 100644
--- a/drivers/net/ethernet/mscc/ocelot_vcap.c
+++ b/drivers/net/ethernet/mscc/ocelot_vcap.c
@@ -1246,7 +1246,11 @@ int ocelot_vcap_filter_del(struct ocelot *ocelot,
struct ocelot_vcap_filter del_filter;
int i, index;
+ /* Need to inherit the block_id so that vcap_entry_set()
+ * does not get confused and knows where to install it.
+ */
memset(&del_filter, 0, sizeof(del_filter));
+ del_filter.block_id = filter->block_id;
/* Gets index of the filter */
index = ocelot_vcap_block_get_filter_index(block, filter);
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 net 3/5] net: mscc: ocelot: fix VCAP IS2 filters matching on both lookups
2022-05-04 23:54 [PATCH v2 net 0/5] Ocelot VCAP fixes Vladimir Oltean
2022-05-04 23:54 ` [PATCH v2 net 1/5] net: mscc: ocelot: mark traps with a bool instead of keeping them in a list Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 2/5] net: mscc: ocelot: fix last VCAP IS1/IS2 filter persisting in hardware when deleted Vladimir Oltean
@ 2022-05-04 23:55 ` Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 4/5] net: mscc: ocelot: restrict tc-trap actions to VCAP IS2 lookup 0 Vladimir Oltean
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Oltean @ 2022-05-04 23:55 UTC (permalink / raw)
To: netdev
Cc: Jakub Kicinski, David S. Miller, Paolo Abeni, Eric Dumazet,
Florian Fainelli, Vivien Didelot, Andrew Lunn, Vladimir Oltean,
Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver, Xiaoliang Yang,
Colin Foster
The VCAP IS2 TCAM is looked up twice per packet, and each filter can be
configured to only match during the first, second lookup, or both, or
none.
The blamed commit wrote the code for making VCAP IS2 filters match only
on the given lookup. But right below that code, there was another line
that explicitly made the lookup a "don't care", and this is overwriting
the lookup we've selected. So the code had no effect.
Some of the more noticeable effects of having filters match on both
lookups:
- in "tc -s filter show dev swp0 ingress", we see each packet matching a
VCAP IS2 filter counted twice. This throws off scripts such as
tools/testing/selftests/net/forwarding/tc_actions.sh and makes them
fail.
- a "tc-drop" action offloaded to VCAP IS2 needs a policer as well,
because once the CPU port becomes a member of the destination port
mask of a packet, nothing removes it, not even a PERMIT/DENY mask mode
with a port mask of 0. But VCAP IS2 rules with the POLICE_ENA bit in
the action vector can only appear in the first lookup. What happens
when a filter matches both lookups is that the action vector is
combined, and this makes the POLICE_ENA bit ineffective, since the
last lookup in which it has appeared is the second one. In other
words, "tc-drop" actions do not drop packets for the CPU port, dropped
packets are still seen by software unless there was an FDB entry that
directed those packets to some other place different from the CPU.
The last bit used to work, because in the initial commit b596229448dd
("net: mscc: ocelot: Add support for tcam"), we were writing the FIRST
field of the VCAP IS2 half key with a 1, not with a "don't care".
The change to "don't care" was made inadvertently by me in commit
c1c3993edb7c ("net: mscc: ocelot: generalize existing code for VCAP"),
which I just realized, and which needs a separate fix from this one,
for "stable" kernels that lack the commit blamed below.
Fixes: 226e9cd82a96 ("net: mscc: ocelot: only install TCAM entries into a specific lookup and PAG")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v2: none
drivers/net/ethernet/mscc/ocelot_vcap.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c
index c08cfcf4c2a2..6de0df1815b7 100644
--- a/drivers/net/ethernet/mscc/ocelot_vcap.c
+++ b/drivers/net/ethernet/mscc/ocelot_vcap.c
@@ -374,7 +374,6 @@ static void is2_entry_set(struct ocelot *ocelot, int ix,
OCELOT_VCAP_BIT_0);
vcap_key_set(vcap, &data, VCAP_IS2_HK_IGR_PORT_MASK, 0,
~filter->ingress_port_mask);
- vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_FIRST, OCELOT_VCAP_BIT_ANY);
vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_HOST_MATCH,
OCELOT_VCAP_BIT_ANY);
vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L2_MC, filter->dmac_mc);
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 net 4/5] net: mscc: ocelot: restrict tc-trap actions to VCAP IS2 lookup 0
2022-05-04 23:54 [PATCH v2 net 0/5] Ocelot VCAP fixes Vladimir Oltean
` (2 preceding siblings ...)
2022-05-04 23:55 ` [PATCH v2 net 3/5] net: mscc: ocelot: fix VCAP IS2 filters matching on both lookups Vladimir Oltean
@ 2022-05-04 23:55 ` Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 5/5] net: mscc: ocelot: avoid corrupting hardware counters when moving VCAP filters Vladimir Oltean
2022-05-06 2:30 ` [PATCH v2 net 0/5] Ocelot VCAP fixes patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Oltean @ 2022-05-04 23:55 UTC (permalink / raw)
To: netdev
Cc: Jakub Kicinski, David S. Miller, Paolo Abeni, Eric Dumazet,
Florian Fainelli, Vivien Didelot, Andrew Lunn, Vladimir Oltean,
Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver, Xiaoliang Yang,
Colin Foster
Once the CPU port was added to the destination port mask of a packet, it
can never be cleared, so even packets marked as dropped by the MASK_MODE
of a VCAP IS2 filter will still reach it. This is why we need the
OCELOT_POLICER_DISCARD to "kill dropped packets dead" and make software
stop seeing them.
We disallow policer rules from being put on any other chain than the one
for the first lookup, but we don't do this for "drop" rules, although we
should. This change is merely ascertaining that the rules dont't
(completely) work and letting the user know.
The blamed commit is the one that introduced the multi-chain architecture
in ocelot. Prior to that, we should have always offloaded the filters to
VCAP IS2 lookup 0, where they did work.
Fixes: 1397a2eb52e2 ("net: mscc: ocelot: create TCAM skeleton from tc filter chains")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v2: none
drivers/net/ethernet/mscc/ocelot_flower.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index a9b26b3002be..51cf241ff7d0 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -280,9 +280,10 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
break;
case FLOW_ACTION_TRAP:
- if (filter->block_id != VCAP_IS2) {
+ if (filter->block_id != VCAP_IS2 ||
+ filter->lookup != 0) {
NL_SET_ERR_MSG_MOD(extack,
- "Trap action can only be offloaded to VCAP IS2");
+ "Trap action can only be offloaded to VCAP IS2 lookup 0");
return -EOPNOTSUPP;
}
if (filter->goto_target != -1) {
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 net 5/5] net: mscc: ocelot: avoid corrupting hardware counters when moving VCAP filters
2022-05-04 23:54 [PATCH v2 net 0/5] Ocelot VCAP fixes Vladimir Oltean
` (3 preceding siblings ...)
2022-05-04 23:55 ` [PATCH v2 net 4/5] net: mscc: ocelot: restrict tc-trap actions to VCAP IS2 lookup 0 Vladimir Oltean
@ 2022-05-04 23:55 ` Vladimir Oltean
2022-05-06 2:30 ` [PATCH v2 net 0/5] Ocelot VCAP fixes patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: Vladimir Oltean @ 2022-05-04 23:55 UTC (permalink / raw)
To: netdev
Cc: Jakub Kicinski, David S. Miller, Paolo Abeni, Eric Dumazet,
Florian Fainelli, Vivien Didelot, Andrew Lunn, Vladimir Oltean,
Claudiu Manoil, Alexandre Belloni, UNGLinuxDriver, Xiaoliang Yang,
Colin Foster
Given the following order of operations:
(1) we add filter A using tc-flower
(2) we send a packet that matches it
(3) we read the filter's statistics to find a hit count of 1
(4) we add a second filter B with a higher preference than A, and A
moves one position to the right to make room in the TCAM for it
(5) we send another packet, and this matches the second filter B
(6) we read the filter statistics again.
When this happens, the hit count of filter A is 2 and of filter B is 1,
despite a single packet having matched each filter.
Furthermore, in an alternate history, reading the filter stats a second
time between steps (3) and (4) makes the hit count of filter A remain at
1 after step (6), as expected.
The reason why this happens has to do with the filter->stats.pkts field,
which is written to hardware through the call path below:
vcap_entry_set
/ | \
/ | \
/ | \
/ | \
es0_entry_set is1_entry_set is2_entry_set
\ | /
\ | /
\ | /
vcap_data_set(data.counter, ...)
The primary role of filter->stats.pkts is to transport the filter hit
counters from the last readout all the way from vcap_entry_get() ->
ocelot_vcap_filter_stats_update() -> ocelot_cls_flower_stats().
The reason why vcap_entry_set() writes it to hardware is so that the
counters (saturating and having a limited bit width) are cleared
after each user space readout.
The writing of filter->stats.pkts to hardware during the TCAM entry
movement procedure is an unintentional consequence of the code design,
because the hit count isn't up to date at this point.
So at step (4), when filter A is moved by ocelot_vcap_filter_add() to
make room for filter B, the hardware hit count is 0 (no packet matched
on it in the meantime), but filter->stats.pkts is 1, because the last
readout saw the earlier packet. The movement procedure programs the old
hit count back to hardware, so this creates the impression to user space
that more packets have been matched than they really were.
The bug can be seen when running the gact_drop_and_ok_test() from the
tc_actions.sh selftest.
Fix the issue by reading back the hit count to tmp->stats.pkts before
migrating the VCAP filter. Sure, this is a best-effort technique, since
the packets that hit the rule between vcap_entry_get() and
vcap_entry_set() won't be counted, but at least it allows the counters
to be reliably used for selftests where the traffic is under control.
The vcap_entry_get() name is a bit unintuitive, but it only reads back
the counter portion of the TCAM entry, not the entire entry.
The index from which we retrieve the counter is also a bit unintuitive
(i - 1 during add, i + 1 during del), but this is the way in which TCAM
entry movement works. The "entry index" isn't a stored integer for a
TCAM filter, instead it is dynamically computed by
ocelot_vcap_block_get_filter_index() based on the entry's position in
the &block->rules list. That position (as well as block->count) is
automatically updated by ocelot_vcap_filter_add_to_block() on add, and
by ocelot_vcap_block_remove_filter() on del. So "i" is the new filter
index, and "i - 1" or "i + 1" respectively are the old addresses of that
TCAM entry (we only support installing/deleting one filter at a time).
Fixes: b596229448dd ("net: mscc: ocelot: Add support for tcam")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v2: none
drivers/net/ethernet/mscc/ocelot_vcap.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c
index 6de0df1815b7..f766471f40dc 100644
--- a/drivers/net/ethernet/mscc/ocelot_vcap.c
+++ b/drivers/net/ethernet/mscc/ocelot_vcap.c
@@ -1212,6 +1212,8 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot,
struct ocelot_vcap_filter *tmp;
tmp = ocelot_vcap_block_find_filter_by_index(block, i);
+ /* Read back the filter's counters before moving it */
+ vcap_entry_get(ocelot, i - 1, tmp);
vcap_entry_set(ocelot, i, tmp);
}
@@ -1264,6 +1266,8 @@ int ocelot_vcap_filter_del(struct ocelot *ocelot,
struct ocelot_vcap_filter *tmp;
tmp = ocelot_vcap_block_find_filter_by_index(block, i);
+ /* Read back the filter's counters before moving it */
+ vcap_entry_get(ocelot, i + 1, tmp);
vcap_entry_set(ocelot, i, tmp);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 net 0/5] Ocelot VCAP fixes
2022-05-04 23:54 [PATCH v2 net 0/5] Ocelot VCAP fixes Vladimir Oltean
` (4 preceding siblings ...)
2022-05-04 23:55 ` [PATCH v2 net 5/5] net: mscc: ocelot: avoid corrupting hardware counters when moving VCAP filters Vladimir Oltean
@ 2022-05-06 2:30 ` patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-05-06 2:30 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, kuba, davem, pabeni, edumazet, f.fainelli, vivien.didelot,
andrew, olteanv, claudiu.manoil, alexandre.belloni,
UNGLinuxDriver, xiaoliang.yang_1, colin.foster
Hello:
This series was applied to netdev/net.git (master)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 5 May 2022 02:54:58 +0300 you wrote:
> Changes in v2:
> fix the NPDs and UAFs caused by filter->trap_list in a more robust way
> that actually does not introduce bugs of its own (1/5)
>
> This series fixes issues found while running
> tools/testing/selftests/net/forwarding/tc_actions.sh on the ocelot
> switch:
>
> [...]
Here is the summary with links:
- [v2,net,1/5] net: mscc: ocelot: mark traps with a bool instead of keeping them in a list
https://git.kernel.org/netdev/net/c/e1846cff2fe6
- [v2,net,2/5] net: mscc: ocelot: fix last VCAP IS1/IS2 filter persisting in hardware when deleted
https://git.kernel.org/netdev/net/c/16bbebd35629
- [v2,net,3/5] net: mscc: ocelot: fix VCAP IS2 filters matching on both lookups
https://git.kernel.org/netdev/net/c/6741e1188000
- [v2,net,4/5] net: mscc: ocelot: restrict tc-trap actions to VCAP IS2 lookup 0
https://git.kernel.org/netdev/net/c/477d2b91623e
- [v2,net,5/5] net: mscc: ocelot: avoid corrupting hardware counters when moving VCAP filters
https://git.kernel.org/netdev/net/c/93a8417088ea
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-05-06 2:30 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-05-04 23:54 [PATCH v2 net 0/5] Ocelot VCAP fixes Vladimir Oltean
2022-05-04 23:54 ` [PATCH v2 net 1/5] net: mscc: ocelot: mark traps with a bool instead of keeping them in a list Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 2/5] net: mscc: ocelot: fix last VCAP IS1/IS2 filter persisting in hardware when deleted Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 3/5] net: mscc: ocelot: fix VCAP IS2 filters matching on both lookups Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 4/5] net: mscc: ocelot: restrict tc-trap actions to VCAP IS2 lookup 0 Vladimir Oltean
2022-05-04 23:55 ` [PATCH v2 net 5/5] net: mscc: ocelot: avoid corrupting hardware counters when moving VCAP filters Vladimir Oltean
2022-05-06 2:30 ` [PATCH v2 net 0/5] Ocelot VCAP fixes patchwork-bot+netdevbpf
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.