Skip to content

Commit

Permalink
net: sched: call reoffload op on block callback reg
Browse files Browse the repository at this point in the history
Call the reoffload tcf_proto_op on all tcf_proto nodes in all chains of a
block when a callback tries to register to a block that already has
offloaded rules. If all existing rules cannot be offloaded then the
registration is rejected. This replaces the previous policy of rejecting
such callback registration outright.

On unregistration of a callback, the rules are flushed for that given cb.
The implementation of block sharing in the NFP driver, for example,
duplicates shared rules to all devs bound to a block. This meant that
rules could still exist in hw even after a device is unbound from a block
(assuming the block still remains active).

Signed-off-by: John Hurley <john.hurley@netronome.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
John Hurley authored and David S. Miller committed Jun 26, 2018
1 parent 7e916b7 commit 3263674
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 12 deletions.
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,7 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,

err_block_bind:
if (!tcf_block_cb_decref(block_cb)) {
__tcf_block_cb_unregister(block_cb);
__tcf_block_cb_unregister(block, block_cb);
err_cb_register:
mlxsw_sp_acl_block_destroy(acl_block);
}
Expand Down Expand Up @@ -1572,7 +1572,7 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
err = mlxsw_sp_acl_block_unbind(mlxsw_sp, acl_block,
mlxsw_sp_port, ingress);
if (!err && !tcf_block_cb_decref(block_cb)) {
__tcf_block_cb_unregister(block_cb);
__tcf_block_cb_unregister(block, block_cb);
mlxsw_sp_acl_block_destroy(acl_block);
}
}
Expand Down
6 changes: 4 additions & 2 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
int tcf_block_cb_register(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident,
void *cb_priv, struct netlink_ext_ack *extack);
void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb);
void __tcf_block_cb_unregister(struct tcf_block *block,
struct tcf_block_cb *block_cb);
void tcf_block_cb_unregister(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident);

Expand Down Expand Up @@ -177,7 +178,8 @@ int tcf_block_cb_register(struct tcf_block *block,
}

static inline
void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb)
void __tcf_block_cb_unregister(struct tcf_block *block,
struct tcf_block_cb *block_cb)
{
}

Expand Down
54 changes: 46 additions & 8 deletions net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -751,19 +751,53 @@ unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
}
EXPORT_SYMBOL(tcf_block_cb_decref);

static int
tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
void *cb_priv, bool add, bool offload_in_use,
struct netlink_ext_ack *extack)
{
struct tcf_chain *chain;
struct tcf_proto *tp;
int err;

list_for_each_entry(chain, &block->chain_list, list) {
for (tp = rtnl_dereference(chain->filter_chain); tp;
tp = rtnl_dereference(tp->next)) {
if (tp->ops->reoffload) {
err = tp->ops->reoffload(tp, add, cb, cb_priv,
extack);
if (err && add)
goto err_playback_remove;
} else if (add && offload_in_use) {
err = -EOPNOTSUPP;
NL_SET_ERR_MSG(extack, "Filter HW offload failed - classifier without re-offloading support");
goto err_playback_remove;
}
}
}

return 0;

err_playback_remove:
tcf_block_playback_offloads(block, cb, cb_priv, false, offload_in_use,
extack);
return err;
}

struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident,
void *cb_priv,
struct netlink_ext_ack *extack)
{
struct tcf_block_cb *block_cb;
int err;

/* At this point, playback of previous block cb calls is not supported,
* so forbid to register to block which already has some offloaded
* filters present.
*/
if (tcf_block_offload_in_use(block))
return ERR_PTR(-EOPNOTSUPP);
/* Replay any already present rules */
err = tcf_block_playback_offloads(block, cb, cb_priv, true,
tcf_block_offload_in_use(block),
extack);
if (err)
return ERR_PTR(err);

block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
if (!block_cb)
Expand All @@ -788,8 +822,12 @@ int tcf_block_cb_register(struct tcf_block *block,
}
EXPORT_SYMBOL(tcf_block_cb_register);

void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb)
void __tcf_block_cb_unregister(struct tcf_block *block,
struct tcf_block_cb *block_cb)
{
tcf_block_playback_offloads(block, block_cb->cb, block_cb->cb_priv,
false, tcf_block_offload_in_use(block),
NULL);
list_del(&block_cb->list);
kfree(block_cb);
}
Expand All @@ -803,7 +841,7 @@ void tcf_block_cb_unregister(struct tcf_block *block,
block_cb = tcf_block_cb_lookup(block, cb, cb_ident);
if (!block_cb)
return;
__tcf_block_cb_unregister(block_cb);
__tcf_block_cb_unregister(block, block_cb);
}
EXPORT_SYMBOL(tcf_block_cb_unregister);

Expand Down

0 comments on commit 3263674

Please sign in to comment.