On Tue, 27 Nov 2018 16:04:29 +0000, Edward Cree wrote:
> On 10/11/18 05:21, Jakub Kicinski wrote:
> > From: John Hurley <john.hur...@netronome.com>
> >
> > Previously, TC block tunnel decap rules were only offloaded when a
> > callback was triggered through registration of the rules egress device.
> > This meant that the driver had no access to the ingress netdev and so
> > could not verify it was the same tunnel type that the rule implied.
> >
> > Register tunnel devices for indirect TC block offloads in NFP, giving
> > access to new rules based on the ingress device rather than egress. Use
> > this to verify the netdev type of VXLAN and Geneve based rules and offload
> > the rules to HW if applicable.
> >
> > Tunnel registration is done via a netdev notifier. On notifier
> > registration, this is triggered for already existing netdevs. This means
> > that NFP can register for offloads from devices that exist before it is
> > loaded (filter rules will be replayed from the TC core). Similarly, on
> > notifier unregister, a call is triggered for each currently active netdev.
> > This allows the driver to unregister any indirect block callbacks that may
> > still be active.
> >
> > Signed-off-by: John Hurley <john.hur...@netronome.com>
> > Reviewed-by: Jakub Kicinski <jakub.kicin...@netronome.com>  
> I've been experimenting with this to try to understand it better, and I'm
>  struggling to understand how the various cb_ident parameters are meant to
>  be used.  In particular:
> > diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c 
> > b/drivers/net/ethernet/netronome/nfp/flower/offload.c
> > index 2c32edfc1a9d..222e1a98cf16 100644
> > --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
> > +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c  
> 
> [...]
> 
> > +int nfp_flower_reg_indir_block_handler(struct nfp_app *app,
> > +                                  struct net_device *netdev,
> > +                                  unsigned long event)
> > +{
> > +   int err;
> > +
> > +   if (!nfp_fl_is_netdev_to_offload(netdev))
> > +           return NOTIFY_OK;
> > +
> > +   if (event == NETDEV_REGISTER) {
> > +           err = __tc_indr_block_cb_register(netdev, app,
> > +                                             nfp_flower_indr_setup_tc_cb,
> > +                                             netdev);  
> Here 'netdev' is passed as cb_ident, meaning that if you have two of these
>  NICs in a system you will (AIUI) get EEXIST when the second one tries to
>  register its indr_block_cb, since both will have the same cb and cb_ident.
> This is because 'netdev' is the netdevice being watched, rather than the
>  netdevice doing the watching.
> AFAICT the right thing to do here would be to pass in 'app' (more generally,
>  the same thing as cb_priv) as that should uniquely identify the watcher
>  (the watchee is already identified by the 'dev' parameter, which is used to
>  obtain the indr_dev on which the cb_list resides).
> 
> Curiously, though you also pass netdev as the cb_ident to
>  tcf_block_cb_register() in nfp_flower_setup_indr_tc_block(), that does not
>  appear to have the same result, as __tcf_block_cb_register() doesn't check
>  for an already existing entry — with the result that
>  tcf_block_cb_unregister() may remove the wrong entry from the list.  If two
>  callers register blocks with the same cb_ident, then one unregisters, the
>  same block will be removed no matter which caller did the unregister.

Ack, thanks for pointing that out.

> It is also concerning that both __tc_indr_block_cb_unregister() and
>  tcf_block_cb_unregister() return void and will silently do nothing if the
>  passed cb_ident is not found.  In my experiments this did not conduce to
>  debuggability; I think they should either WARN_ON, or at least return
>  (int) -ENOENT so that the caller has the opportunity to do so.

WARN_ON() seems reasonable, returning ENOENT would only push that
WARN_ON() to the drivers, I don't see what else the driver could do
with an error on unregister :)

Reply via email to