Author: erj
Date: Mon Apr 27 22:02:44 2020
New Revision: 360398
URL: https://svnweb.freebsd.org/changeset/base/360398

Log:
  iflib: Stop interface before (un)registering VLAN
  
  This patch is intended to solve a specific problem that iavf(4)
  encounters, but what it does can be extended to solve other issues.
  
  To summarize the iavf(4) issue, if the PF driver configures VLAN
  anti-spoof, then the VF driver needs to make sure no untagged traffic is
  sent if a VLAN is configured, and vice-versa. This can be an issue when
  a VLAN is being registered or unregistered, e.g. when a packet may be on
  the ring with a VLAN in it, but the VLANs are being unregistered. This
  can cause that tagged packet to go out and cause an MDD event.
  
  To fix this, include a new interface-dependent function that drivers can
  implement named IFDI_NEEDS_RESTART(). Right now, this function is called
  in iflib_vlan_unregister/register() to determine whether the interface
  needs to be stopped and started when a VLAN is registered or
  unregistered. The default return value of IFDI_NEEDS_RESTART() is true,
  so this fixes the MDD problem that iavf(4) encounters, since the
  interface rings are flushed during a stop/init.
  
  A future change to iavf(4) will implement that function just in case the
  default value changes, and to make it explicit that this interface reset
  is required when a VLAN is added or removed.
  
  Reviewed by:  gallatin@
  MFC after:    1 week
  Sponsored by: Intel Corporation
  Differential Revision:        https://reviews.freebsd.org/D22086

Modified:
  head/sys/net/ifdi_if.m
  head/sys/net/iflib.c
  head/sys/net/iflib.h

Modified: head/sys/net/ifdi_if.m
==============================================================================
--- head/sys/net/ifdi_if.m      Mon Apr 27 21:51:22 2020        (r360397)
+++ head/sys/net/ifdi_if.m      Mon Apr 27 22:02:44 2020        (r360398)
@@ -169,6 +169,12 @@ CODE {
            }
            return (0);
        }
+
+       static bool
+       null_needs_restart(if_ctx_t _ctx __unused, enum iflib_restart_event 
_event __unused)
+       {
+               return (true);
+       }
 };
 
 #
@@ -456,3 +462,8 @@ METHOD int sysctl_int_delay {
 METHOD void debug {
        if_ctx_t _ctx;
 } DEFAULT null_void_op;
+
+METHOD bool needs_restart {
+       if_ctx_t _ctx;
+       enum iflib_restart_event _event;
+} DEFAULT null_needs_restart;

Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c        Mon Apr 27 21:51:22 2020        (r360397)
+++ head/sys/net/iflib.c        Mon Apr 27 22:02:44 2020        (r360398)
@@ -4308,10 +4308,13 @@ iflib_vlan_register(void *arg, if_t ifp, uint16_t vtag
                return;
 
        CTX_LOCK(ctx);
+       /* Driver may need all untagged packets to be flushed */
+       if (IFDI_NEEDS_RESTART(ctx, IFLIB_RESTART_VLAN_CONFIG))
+               iflib_stop(ctx);
        IFDI_VLAN_REGISTER(ctx, vtag);
-       /* Re-init to load the changes */
-       if (if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER)
-               iflib_if_init_locked(ctx);
+       /* Re-init to load the changes, if required */
+       if (IFDI_NEEDS_RESTART(ctx, IFLIB_RESTART_VLAN_CONFIG))
+               iflib_init_locked(ctx);
        CTX_UNLOCK(ctx);
 }
 
@@ -4327,10 +4330,13 @@ iflib_vlan_unregister(void *arg, if_t ifp, uint16_t vt
                return;
 
        CTX_LOCK(ctx);
+       /* Driver may need all tagged packets to be flushed */
+       if (IFDI_NEEDS_RESTART(ctx, IFLIB_RESTART_VLAN_CONFIG))
+               iflib_stop(ctx);
        IFDI_VLAN_UNREGISTER(ctx, vtag);
-       /* Re-init to load the changes */
-       if (if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER)
-               iflib_if_init_locked(ctx);
+       /* Re-init to load the changes, if required */
+       if (IFDI_NEEDS_RESTART(ctx, IFLIB_RESTART_VLAN_CONFIG))
+               iflib_init_locked(ctx);
        CTX_UNLOCK(ctx);
 }
 

Modified: head/sys/net/iflib.h
==============================================================================
--- head/sys/net/iflib.h        Mon Apr 27 21:51:22 2020        (r360397)
+++ head/sys/net/iflib.h        Mon Apr 27 22:02:44 2020        (r360398)
@@ -377,6 +377,15 @@ typedef enum {
 #define        IFLIB_SINGLE_IRQ_RX_ONLY        0x40000
 
 /*
+ * These enum values are used in iflib_needs_restart to indicate to iflib
+ * functions whether or not the interface needs restarting when certain events
+ * happen.
+ */
+enum iflib_restart_event {
+       IFLIB_RESTART_VLAN_CONFIG,
+};
+
+/*
  * field accessors
  */
 void *iflib_get_softc(if_ctx_t ctx);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to