Implement VLAN hardware filter function(ETHERCAP_VLAN_HWFILTER).
First proposed by jmcneill in 2017 and modified by me. How to use: - Set callback function: ether_set_vlan_cb(struct ethercom *, ether_vlancb_t) - Callback. This function is called when a vlan is attached/detached to the parent interface: int (*ether_vlancb_t)(struct ethercom *ec, uint16_t vlanid, bool set); - ifconfig(8) ifconfig ixg0 [-]vlan-hwfilter Note that ETHERCAP_VLAN_HWFILTER is set by default on ixg(4) because the PF driver usually enable "all block" filter by default.
This commit is contained in:
parent
cb1ccde89c
commit
eea2ee1212
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ether.c,v 1.5 2019/07/17 03:09:16 msaitoh Exp $ */
|
||||
/* $NetBSD: ether.c,v 1.6 2019/07/17 03:26:24 msaitoh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: ether.c,v 1.5 2019/07/17 03:09:16 msaitoh Exp $");
|
||||
__RCSID("$NetBSD: ether.c,v 1.6 2019/07/17 03:26:24 msaitoh Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -64,9 +64,7 @@ static cmdloop_branch_t branch;
|
||||
#define MAX_PRINT_LEN 55
|
||||
|
||||
static const struct kwinst ethercapskw[] = {
|
||||
#if 0 /* notyet */
|
||||
IFKW("vlan-hwfilter", ETHERCAP_VLAN_HWFILTER),
|
||||
#endif
|
||||
IFKW("vlan-hwtagging", ETHERCAP_VLAN_HWTAGGING),
|
||||
IFKW("eee", ETHERCAP_EEE)
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ixgbe.c,v 1.192 2019/07/04 09:02:24 msaitoh Exp $ */
|
||||
/* $NetBSD: ixgbe.c,v 1.193 2019/07/17 03:26:24 msaitoh Exp $ */
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@ -220,10 +220,9 @@ static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
|
||||
static void ixgbe_eitr_write(struct adapter *, uint32_t, uint32_t);
|
||||
|
||||
static void ixgbe_setup_vlan_hw_support(struct adapter *);
|
||||
#if 0
|
||||
static void ixgbe_register_vlan(void *, struct ifnet *, u16);
|
||||
static void ixgbe_unregister_vlan(void *, struct ifnet *, u16);
|
||||
#endif
|
||||
static int ixgbe_vlan_cb(struct ethercom *, uint16_t, bool);
|
||||
static int ixgbe_register_vlan(void *, struct ifnet *, u16);
|
||||
static int ixgbe_unregister_vlan(void *, struct ifnet *, u16);
|
||||
|
||||
static void ixgbe_add_device_sysctls(struct adapter *);
|
||||
static void ixgbe_add_hw_stats(struct adapter *);
|
||||
@ -905,6 +904,9 @@ ixgbe_attach(device_t parent, device_t dev, void *aux)
|
||||
/* Enable WoL (if supported) */
|
||||
ixgbe_check_wol_support(adapter);
|
||||
|
||||
/* Register for VLAN events */
|
||||
ether_set_vlan_cb(&adapter->osdep.ec, ixgbe_vlan_cb);
|
||||
|
||||
/* Verify adapter fan is still functional (if applicable) */
|
||||
if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
|
||||
u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
||||
@ -2299,7 +2301,20 @@ ixgbe_sysctl_rdt_handler(SYSCTLFN_ARGS)
|
||||
return sysctl_lookup(SYSCTLFN_CALL(&node));
|
||||
} /* ixgbe_sysctl_rdt_handler */
|
||||
|
||||
#if 0 /* XXX Badly need to overhaul vlan(4) on NetBSD. */
|
||||
static int
|
||||
ixgbe_vlan_cb(struct ethercom *ec, uint16_t vid, bool set)
|
||||
{
|
||||
struct ifnet *ifp = &ec->ec_if;
|
||||
int rv;
|
||||
|
||||
if (set)
|
||||
rv = ixgbe_register_vlan(ifp->if_softc, ifp, vid);
|
||||
else
|
||||
rv = ixgbe_unregister_vlan(ifp->if_softc, ifp, vid);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* ixgbe_register_vlan
|
||||
*
|
||||
@ -2308,24 +2323,30 @@ ixgbe_sysctl_rdt_handler(SYSCTLFN_ARGS)
|
||||
* just creates the entry in the soft version of the
|
||||
* VFTA, init will repopulate the real table.
|
||||
************************************************************************/
|
||||
static void
|
||||
static int
|
||||
ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
|
||||
{
|
||||
struct adapter *adapter = ifp->if_softc;
|
||||
u16 index, bit;
|
||||
int error;
|
||||
|
||||
if (ifp->if_softc != arg) /* Not our event */
|
||||
return;
|
||||
return EINVAL;
|
||||
|
||||
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
|
||||
return;
|
||||
return EINVAL;
|
||||
|
||||
IXGBE_CORE_LOCK(adapter);
|
||||
index = (vtag >> 5) & 0x7F;
|
||||
bit = vtag & 0x1F;
|
||||
adapter->shadow_vfta[index] |= (1 << bit);
|
||||
ixgbe_setup_vlan_hw_support(adapter);
|
||||
error = adapter->hw.mac.ops.set_vfta(&adapter->hw, vtag, 0, true,
|
||||
true);
|
||||
IXGBE_CORE_UNLOCK(adapter);
|
||||
if (error != 0)
|
||||
error = EACCES;
|
||||
|
||||
return error;
|
||||
} /* ixgbe_register_vlan */
|
||||
|
||||
/************************************************************************
|
||||
@ -2333,27 +2354,31 @@ ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
|
||||
*
|
||||
* Run via vlan unconfig EVENT, remove our entry in the soft vfta.
|
||||
************************************************************************/
|
||||
static void
|
||||
static int
|
||||
ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
|
||||
{
|
||||
struct adapter *adapter = ifp->if_softc;
|
||||
u16 index, bit;
|
||||
int error;
|
||||
|
||||
if (ifp->if_softc != arg)
|
||||
return;
|
||||
return EINVAL;
|
||||
|
||||
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
|
||||
return;
|
||||
return EINVAL;
|
||||
|
||||
IXGBE_CORE_LOCK(adapter);
|
||||
index = (vtag >> 5) & 0x7F;
|
||||
bit = vtag & 0x1F;
|
||||
adapter->shadow_vfta[index] &= ~(1 << bit);
|
||||
/* Re-init to load the changes */
|
||||
ixgbe_setup_vlan_hw_support(adapter);
|
||||
error = adapter->hw.mac.ops.set_vfta(&adapter->hw, vtag, 0, false,
|
||||
true);
|
||||
IXGBE_CORE_UNLOCK(adapter);
|
||||
if (error != 0)
|
||||
error = EACCES;
|
||||
|
||||
return error;
|
||||
} /* ixgbe_unregister_vlan */
|
||||
#endif
|
||||
|
||||
static void
|
||||
ixgbe_setup_vlan_hw_support(struct adapter *adapter)
|
||||
@ -2363,6 +2388,7 @@ ixgbe_setup_vlan_hw_support(struct adapter *adapter)
|
||||
struct rx_ring *rxr;
|
||||
int i;
|
||||
u32 ctrl;
|
||||
struct vlanid_list *vlanidp;
|
||||
bool hwtagging;
|
||||
|
||||
/*
|
||||
@ -2391,14 +2417,21 @@ ixgbe_setup_vlan_hw_support(struct adapter *adapter)
|
||||
rxr->vtag_strip = hwtagging ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* A soft reset zero's out the VFTA, so
|
||||
* we need to repopulate it now.
|
||||
*/
|
||||
/* Cleanup shadow_vfta */
|
||||
for (i = 0; i < IXGBE_VFTA_SIZE; i++)
|
||||
if (adapter->shadow_vfta[i] != 0)
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
|
||||
adapter->shadow_vfta[i]);
|
||||
adapter->shadow_vfta[i] = 0;
|
||||
/* Generate shadow_vfta from ec_vids */
|
||||
mutex_enter(ec->ec_lock);
|
||||
SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) {
|
||||
uint32_t idx;
|
||||
|
||||
idx = vlanidp->vid / 32;
|
||||
KASSERT(idx < IXGBE_VFTA_SIZE);
|
||||
adapter->shadow_vfta[idx] |= 1 << vlanidp->vid % 32;
|
||||
}
|
||||
mutex_exit(ec->ec_lock);
|
||||
for (i = 0; i < IXGBE_VFTA_SIZE; i++)
|
||||
IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), adapter->shadow_vfta[i]);
|
||||
|
||||
ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
|
||||
/* Enable the Filter Table if enabled */
|
||||
@ -4107,6 +4140,7 @@ ixgbe_init_locked(struct adapter *adapter)
|
||||
|
||||
/* Update saved flags. See ixgbe_ifflags_cb() */
|
||||
adapter->if_flags = ifp->if_flags;
|
||||
adapter->ec_capenable = adapter->osdep.ec.ec_capenable;
|
||||
|
||||
/* Now inform the stack we're ready */
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
@ -6151,8 +6185,23 @@ ixgbe_ifflags_cb(struct ethercom *ec)
|
||||
} else if ((change & IFF_PROMISC) != 0)
|
||||
ixgbe_set_promisc(adapter);
|
||||
|
||||
/* Check for ec_capenable. */
|
||||
change = ec->ec_capenable ^ adapter->ec_capenable;
|
||||
adapter->ec_capenable = ec->ec_capenable;
|
||||
if ((change & ~(ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING
|
||||
| ETHERCAP_VLAN_HWFILTER)) != 0) {
|
||||
rv = ENETRESET;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special handling is not required for ETHERCAP_VLAN_MTU.
|
||||
* MAXFRS(MHADD) does not include the 4bytes of the VLAN header.
|
||||
*/
|
||||
|
||||
/* Set up VLAN support and filter */
|
||||
ixgbe_setup_vlan_hw_support(adapter);
|
||||
if ((change & (ETHERCAP_VLAN_HWTAGGING | ETHERCAP_VLAN_HWFILTER)) != 0)
|
||||
ixgbe_setup_vlan_hw_support(adapter);
|
||||
|
||||
out:
|
||||
IXGBE_CORE_UNLOCK(adapter);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ixgbe.h,v 1.55 2019/06/27 05:55:40 msaitoh Exp $ */
|
||||
/* $NetBSD: ixgbe.h,v 1.56 2019/07/17 03:26:24 msaitoh Exp $ */
|
||||
|
||||
/******************************************************************************
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
@ -475,7 +475,8 @@ struct adapter {
|
||||
|
||||
struct ifmedia media;
|
||||
callout_t timer;
|
||||
int if_flags;
|
||||
int if_flags; /* saved ifp->if_flags */
|
||||
int ec_capenable; /* saved ec->ec_capenable */
|
||||
|
||||
kmutex_t core_mtx;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*$NetBSD: ixv.c,v 1.119 2019/07/17 03:09:16 msaitoh Exp $*/
|
||||
/*$NetBSD: ixv.c,v 1.120 2019/07/17 03:26:24 msaitoh Exp $*/
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@ -120,11 +120,10 @@ static void ixv_configure_ivars(struct adapter *);
|
||||
static u8 * ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
|
||||
static void ixv_eitr_write(struct adapter *, uint32_t, uint32_t);
|
||||
|
||||
static void ixv_setup_vlan_support(struct adapter *);
|
||||
#if 0
|
||||
static void ixv_register_vlan(void *, struct ifnet *, u16);
|
||||
static void ixv_unregister_vlan(void *, struct ifnet *, u16);
|
||||
#endif
|
||||
static int ixv_setup_vlan_support(struct adapter *);
|
||||
static int ixv_vlan_cb(struct ethercom *, uint16_t, bool);
|
||||
static int ixv_register_vlan(void *, struct ifnet *, u16);
|
||||
static int ixv_unregister_vlan(void *, struct ifnet *, u16);
|
||||
|
||||
static void ixv_add_device_sysctls(struct adapter *);
|
||||
static void ixv_save_stats(struct adapter *);
|
||||
@ -471,12 +470,7 @@ ixv_attach(device_t parent, device_t dev, void *aux)
|
||||
}
|
||||
|
||||
/* Register for VLAN events */
|
||||
#if 0 /* XXX delete after write? */
|
||||
adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
|
||||
ixv_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
|
||||
adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
|
||||
ixv_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
|
||||
#endif
|
||||
ether_set_vlan_cb(&adapter->osdep.ec, ixv_vlan_cb);
|
||||
|
||||
/* Sysctls for limiting the amount of work done in the taskqueues */
|
||||
ixv_set_sysctl_value(adapter, "rx_processing_limit",
|
||||
@ -618,14 +612,6 @@ ixv_detach(device_t dev, int flags)
|
||||
/* Drain the Mailbox(link) queue */
|
||||
softint_disestablish(adapter->link_si);
|
||||
|
||||
/* Unregister VLAN events */
|
||||
#if 0 /* XXX msaitoh delete after write? */
|
||||
if (adapter->vlan_attach != NULL)
|
||||
EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
|
||||
if (adapter->vlan_detach != NULL)
|
||||
EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
|
||||
#endif
|
||||
|
||||
ether_ifdetach(adapter->ifp);
|
||||
callout_halt(&adapter->timer, NULL);
|
||||
|
||||
@ -823,6 +809,7 @@ ixv_init_locked(struct adapter *adapter)
|
||||
|
||||
/* Update saved flags. See ixgbe_ifflags_cb() */
|
||||
adapter->if_flags = ifp->if_flags;
|
||||
adapter->ec_capenable = adapter->osdep.ec.ec_capenable;
|
||||
|
||||
/* Now inform the stack we're ready */
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
@ -1557,7 +1544,8 @@ ixv_setup_interface(device_t dev, struct adapter *adapter)
|
||||
| IFCAP_TSOv6;
|
||||
ifp->if_capenable = 0;
|
||||
|
||||
ec->ec_capabilities |= ETHERCAP_VLAN_HWTAGGING
|
||||
ec->ec_capabilities |= ETHERCAP_VLAN_HWFILTER
|
||||
| ETHERCAP_VLAN_HWTAGGING
|
||||
| ETHERCAP_VLAN_HWCSUM
|
||||
| ETHERCAP_JUMBO_MTU
|
||||
| ETHERCAP_VLAN_MTU;
|
||||
@ -1954,19 +1942,23 @@ ixv_sysctl_rdt_handler(SYSCTLFN_ARGS)
|
||||
/************************************************************************
|
||||
* ixv_setup_vlan_support
|
||||
************************************************************************/
|
||||
static void
|
||||
static int
|
||||
ixv_setup_vlan_support(struct adapter *adapter)
|
||||
{
|
||||
struct ethercom *ec = &adapter->osdep.ec;
|
||||
struct ixgbe_hw *hw = &adapter->hw;
|
||||
struct rx_ring *rxr;
|
||||
u32 ctrl, vid, vfta, retry;
|
||||
struct vlanid_list *vlanidp;
|
||||
int rv, error = 0;
|
||||
bool usevlan;
|
||||
bool hwtagging;
|
||||
|
||||
/*
|
||||
* This function is called from both if_init and ifflags_cb()
|
||||
* on NetBSD.
|
||||
*/
|
||||
usevlan = VLAN_ATTACHED(ec);
|
||||
|
||||
/* Enable HW tagging only if any vlan is attached */
|
||||
hwtagging = (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING)
|
||||
@ -1988,11 +1980,23 @@ ixv_setup_vlan_support(struct adapter *adapter)
|
||||
rxr->vtag_strip = hwtagging ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/* XXX dirty hack. Enable all VIDs if any VLAN is attached */
|
||||
for (int i = 0; i < IXGBE_VFTA_SIZE; i++)
|
||||
adapter->shadow_vfta[i]
|
||||
= VLAN_ATTACHED(&adapter->osdep.ec) ? 0xffffffff : 0;
|
||||
if (!usevlan)
|
||||
return 0;
|
||||
|
||||
/* Cleanup shadow_vfta */
|
||||
for (int i = 0; i < IXGBE_VFTA_SIZE; i++)
|
||||
adapter->shadow_vfta[i] = 0;
|
||||
/* Generate shadow_vfta from ec_vids */
|
||||
mutex_enter(ec->ec_lock);
|
||||
SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) {
|
||||
uint32_t idx;
|
||||
|
||||
idx = vlanidp->vid / 32;
|
||||
KASSERT(idx < IXGBE_VFTA_SIZE);
|
||||
adapter->shadow_vfta[idx] |= 1 << vlanidp->vid % 32;
|
||||
}
|
||||
mutex_exit(ec->ec_lock);
|
||||
|
||||
/*
|
||||
* A soft reset zero's out the VFTA, so
|
||||
* we need to repopulate it now.
|
||||
@ -2011,16 +2015,41 @@ ixv_setup_vlan_support(struct adapter *adapter)
|
||||
if ((vfta & (1 << j)) == 0)
|
||||
continue;
|
||||
vid = (i * 32) + j;
|
||||
|
||||
/* Call the shared code mailbox routine */
|
||||
while (hw->mac.ops.set_vfta(hw, vid, 0, TRUE, FALSE)) {
|
||||
if (++retry > 5)
|
||||
while ((rv = hw->mac.ops.set_vfta(hw, vid, 0, TRUE,
|
||||
FALSE)) != 0) {
|
||||
if (++retry > 5) {
|
||||
device_printf(adapter->dev,
|
||||
"%s: max retry exceeded\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rv != 0) {
|
||||
device_printf(adapter->dev,
|
||||
"failed to set vlan %d\n", vid);
|
||||
error = EACCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
} /* ixv_setup_vlan_support */
|
||||
|
||||
#if 0 /* XXX Badly need to overhaul vlan(4) on NetBSD. */
|
||||
static int
|
||||
ixv_vlan_cb(struct ethercom *ec, uint16_t vid, bool set)
|
||||
{
|
||||
struct ifnet *ifp = &ec->ec_if;
|
||||
int rv;
|
||||
|
||||
if (set)
|
||||
rv = ixv_register_vlan(ifp->if_softc, ifp, vid);
|
||||
else
|
||||
rv = ixv_unregister_vlan(ifp->if_softc, ifp, vid);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* ixv_register_vlan
|
||||
*
|
||||
@ -2029,25 +2058,32 @@ ixv_setup_vlan_support(struct adapter *adapter)
|
||||
* creates the entry in the soft version of the VFTA, init
|
||||
* will repopulate the real table.
|
||||
************************************************************************/
|
||||
static void
|
||||
static int
|
||||
ixv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
|
||||
{
|
||||
struct adapter *adapter = ifp->if_softc;
|
||||
struct ixgbe_hw *hw = &adapter->hw;
|
||||
u16 index, bit;
|
||||
int error;
|
||||
|
||||
if (ifp->if_softc != arg) /* Not our event */
|
||||
return;
|
||||
return EINVAL;
|
||||
|
||||
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
|
||||
return;
|
||||
|
||||
return EINVAL;
|
||||
IXGBE_CORE_LOCK(adapter);
|
||||
index = (vtag >> 5) & 0x7F;
|
||||
bit = vtag & 0x1F;
|
||||
adapter->shadow_vfta[index] |= (1 << bit);
|
||||
/* Re-init to load the changes */
|
||||
ixv_init_locked(adapter);
|
||||
error = hw->mac.ops.set_vfta(hw, vtag, 0, true, false);
|
||||
IXGBE_CORE_UNLOCK(adapter);
|
||||
|
||||
if (error != 0) {
|
||||
device_printf(adapter->dev, "failed to register vlan %hu\n",
|
||||
vtag);
|
||||
error = EACCES;
|
||||
}
|
||||
return error;
|
||||
} /* ixv_register_vlan */
|
||||
|
||||
/************************************************************************
|
||||
@ -2056,27 +2092,34 @@ ixv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
|
||||
* Run via a vlan unconfig EVENT, remove our entry
|
||||
* in the soft vfta.
|
||||
************************************************************************/
|
||||
static void
|
||||
static int
|
||||
ixv_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
|
||||
{
|
||||
struct adapter *adapter = ifp->if_softc;
|
||||
struct ixgbe_hw *hw = &adapter->hw;
|
||||
u16 index, bit;
|
||||
int error;
|
||||
|
||||
if (ifp->if_softc != arg)
|
||||
return;
|
||||
return EINVAL;
|
||||
|
||||
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
|
||||
return;
|
||||
return EINVAL;
|
||||
|
||||
IXGBE_CORE_LOCK(adapter);
|
||||
index = (vtag >> 5) & 0x7F;
|
||||
bit = vtag & 0x1F;
|
||||
adapter->shadow_vfta[index] &= ~(1 << bit);
|
||||
/* Re-init to load the changes */
|
||||
ixv_init_locked(adapter);
|
||||
error = hw->mac.ops.set_vfta(hw, vtag, 0, false, false);
|
||||
IXGBE_CORE_UNLOCK(adapter);
|
||||
|
||||
if (error != 0) {
|
||||
device_printf(adapter->dev, "failed to unregister vlan %hu\n",
|
||||
vtag);
|
||||
error = EIO;
|
||||
}
|
||||
return error;
|
||||
} /* ixv_unregister_vlan */
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
* ixv_enable_intr
|
||||
@ -2742,8 +2785,23 @@ ixv_ifflags_cb(struct ethercom *ec)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check for ec_capenable. */
|
||||
change = ec->ec_capenable ^ adapter->ec_capenable;
|
||||
adapter->ec_capenable = ec->ec_capenable;
|
||||
if ((change & ~(ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING
|
||||
| ETHERCAP_VLAN_HWFILTER)) != 0) {
|
||||
rv = ENETRESET;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special handling is not required for ETHERCAP_VLAN_MTU.
|
||||
* PF's MAXFRS(MHADD) does not include the 4bytes of the VLAN header.
|
||||
*/
|
||||
|
||||
/* Set up VLAN support and filter */
|
||||
ixv_setup_vlan_support(adapter);
|
||||
if ((change & (ETHERCAP_VLAN_HWTAGGING | ETHERCAP_VLAN_HWFILTER)) != 0)
|
||||
rv = ixv_setup_vlan_support(adapter);
|
||||
|
||||
out:
|
||||
IXGBE_CORE_UNLOCK(adapter);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_ether.h,v 1.80 2019/07/17 03:09:16 msaitoh Exp $ */
|
||||
/* $NetBSD: if_ether.h,v 1.81 2019/07/17 03:26:24 msaitoh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
@ -163,6 +163,7 @@ struct mii_data;
|
||||
struct ethercom;
|
||||
|
||||
typedef int (*ether_cb_t)(struct ethercom *);
|
||||
typedef int (*ether_vlancb_t)(struct ethercom *, uint16_t, bool);
|
||||
|
||||
/*
|
||||
* Structure shared between the ethernet driver modules and
|
||||
@ -181,6 +182,7 @@ struct ethercom {
|
||||
capabilities to enable */
|
||||
|
||||
int ec_nvlans; /* # VLANs on this interface */
|
||||
SIMPLEQ_HEAD(, vlanid_list) ec_vids; /* list of VLAN IDs */
|
||||
/* The device handle for the MII bus child device. */
|
||||
struct mii_data *ec_mii;
|
||||
struct ifmedia *ec_ifmedia;
|
||||
@ -190,6 +192,12 @@ struct ethercom {
|
||||
* ec_if.if_init, 0 on success, not 0 on failure.
|
||||
*/
|
||||
ether_cb_t ec_ifflags_cb;
|
||||
/*
|
||||
* Called whenever a vlan interface is configured or unconfigured.
|
||||
* Args include the vlan tag and a flag indicating whether the tag is
|
||||
* being added or removed.
|
||||
*/
|
||||
ether_vlancb_t ec_vlan_cb;
|
||||
kmutex_t *ec_lock;
|
||||
/* Flags used only by the kernel */
|
||||
int ec_flags;
|
||||
@ -241,6 +249,7 @@ extern const uint8_t ether_ipmulticast_min[ETHER_ADDR_LEN];
|
||||
extern const uint8_t ether_ipmulticast_max[ETHER_ADDR_LEN];
|
||||
|
||||
void ether_set_ifflags_cb(struct ethercom *, ether_cb_t);
|
||||
void ether_set_vlan_cb(struct ethercom *, ether_vlancb_t);
|
||||
int ether_ioctl(struct ifnet *, u_long, void *);
|
||||
int ether_addmulti(const struct sockaddr *, struct ethercom *);
|
||||
int ether_delmulti(const struct sockaddr *, struct ethercom *);
|
||||
@ -336,6 +345,12 @@ ether_first_multi(struct ether_multistep *step, const struct ethercom *ec)
|
||||
* Ethernet 802.1Q VLAN structures.
|
||||
*/
|
||||
|
||||
/* for ethercom */
|
||||
struct vlanid_list {
|
||||
uint16_t vid;
|
||||
SIMPLEQ_ENTRY(vlanid_list) vid_list;
|
||||
};
|
||||
|
||||
/* add VLAN tag to input/received packet */
|
||||
static __inline void
|
||||
vlan_set_tag(struct mbuf *m, uint16_t vlantag)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_ethersubr.c,v 1.275 2019/05/29 10:07:30 msaitoh Exp $ */
|
||||
/* $NetBSD: if_ethersubr.c,v 1.276 2019/07/17 03:26:24 msaitoh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -61,7 +61,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.275 2019/05/29 10:07:30 msaitoh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.276 2019/07/17 03:26:24 msaitoh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
@ -996,6 +996,7 @@ ether_ifattach(struct ifnet *ifp, const uint8_t *lla)
|
||||
if_set_sadl(ifp, lla, ETHER_ADDR_LEN, !ETHER_IS_LOCAL(lla));
|
||||
|
||||
LIST_INIT(&ec->ec_multiaddrs);
|
||||
SIMPLEQ_INIT(&ec->ec_vids);
|
||||
ec->ec_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
|
||||
ec->ec_flags = 0;
|
||||
ifp->if_broadcastaddr = etherbroadcastaddr;
|
||||
@ -1042,6 +1043,7 @@ ether_ifdetach(struct ifnet *ifp)
|
||||
#endif
|
||||
|
||||
ETHER_LOCK(ec);
|
||||
KASSERT(ec->ec_nvlans == 0);
|
||||
while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) {
|
||||
LIST_REMOVE(enm, enm_list);
|
||||
kmem_free(enm, sizeof(*enm));
|
||||
@ -1372,6 +1374,13 @@ ether_set_ifflags_cb(struct ethercom *ec, ether_cb_t cb)
|
||||
ec->ec_ifflags_cb = cb;
|
||||
}
|
||||
|
||||
void
|
||||
ether_set_vlan_cb(struct ethercom *ec, ether_vlancb_t cb)
|
||||
{
|
||||
|
||||
ec->ec_vlan_cb = cb;
|
||||
}
|
||||
|
||||
static int
|
||||
ether_ioctl_reinit(struct ethercom *ec)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_vlan.c,v 1.140 2019/07/17 03:09:16 msaitoh Exp $ */
|
||||
/* $NetBSD: if_vlan.c,v 1.141 2019/07/17 03:26:24 msaitoh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
|
||||
@ -78,7 +78,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.140 2019/07/17 03:09:16 msaitoh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.141 2019/07/17 03:26:24 msaitoh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
@ -130,15 +130,10 @@ struct vlan_mc_entry {
|
||||
* used since multiple sockaddr may mapped into the same
|
||||
* ether_multi (e.g., AF_UNSPEC).
|
||||
*/
|
||||
union {
|
||||
struct ether_multi *mcu_enm;
|
||||
} mc_u;
|
||||
struct ether_multi *mc_enm;
|
||||
struct sockaddr_storage mc_addr;
|
||||
};
|
||||
|
||||
#define mc_enm mc_u.mcu_enm
|
||||
|
||||
|
||||
struct ifvlan_linkmib {
|
||||
struct ifvlan *ifvm_ifvlan;
|
||||
const struct vlan_multisw *ifvm_msw;
|
||||
@ -153,9 +148,7 @@ struct ifvlan_linkmib {
|
||||
};
|
||||
|
||||
struct ifvlan {
|
||||
union {
|
||||
struct ethercom ifvu_ec;
|
||||
} ifv_u;
|
||||
struct ethercom ifv_ec;
|
||||
struct ifvlan_linkmib *ifv_mib; /*
|
||||
* reader must use vlan_getref_linkmib()
|
||||
* instead of direct dereference
|
||||
@ -171,8 +164,6 @@ struct ifvlan {
|
||||
|
||||
#define IFVF_PROMISC 0x01 /* promiscuous mode enabled */
|
||||
|
||||
#define ifv_ec ifv_u.ifvu_ec
|
||||
|
||||
#define ifv_if ifv_ec.ec_if
|
||||
|
||||
#define ifv_msw ifv_mib.ifvm_msw
|
||||
@ -466,6 +457,8 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag)
|
||||
case IFT_ETHER:
|
||||
{
|
||||
struct ethercom *ec = (void *)p;
|
||||
struct vlanid_list *vidmem;
|
||||
|
||||
nmib->ifvm_msw = &vlan_ether_multisw;
|
||||
nmib->ifvm_encaplen = ETHER_VLAN_ENCAP_LEN;
|
||||
nmib->ifvm_mintu = ETHERMIN;
|
||||
@ -492,7 +485,36 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag)
|
||||
}
|
||||
error = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a vid to the list even if it's not enabled in case
|
||||
* it's enabled later.
|
||||
*/
|
||||
if (ec->ec_capabilities & ETHERCAP_VLAN_HWFILTER) {
|
||||
vidmem = kmem_alloc(sizeof(struct vlanid_list),
|
||||
KM_SLEEP);
|
||||
if (vidmem == NULL){
|
||||
ec->ec_nvlans--;
|
||||
if (ec->ec_nvlans == 0)
|
||||
(void)ether_disable_vlan_mtu(p);
|
||||
error = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
vidmem->vid = vid;
|
||||
mutex_enter(ec->ec_lock);
|
||||
SIMPLEQ_INSERT_TAIL(&ec->ec_vids, vidmem, vid_list);
|
||||
mutex_exit(ec->ec_lock);
|
||||
}
|
||||
if (ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) {
|
||||
if (ec->ec_vlan_cb != NULL) {
|
||||
error = (*ec->ec_vlan_cb)(ec, vid, true);
|
||||
if (error) {
|
||||
ec->ec_nvlans--;
|
||||
if (ec->ec_nvlans == 0)
|
||||
(void)ether_disable_vlan_mtu(p);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If the parent interface can do hardware-assisted
|
||||
* VLAN encapsulation, then propagate its hardware-
|
||||
@ -618,6 +640,20 @@ vlan_unconfig_locked(struct ifvlan *ifv, struct ifvlan_linkmib *nmib)
|
||||
case IFT_ETHER:
|
||||
{
|
||||
struct ethercom *ec = (void *)p;
|
||||
struct vlanid_list *vlanidp, *tmpp;
|
||||
uint16_t vid = EVL_VLANOFTAG(nmib->ifvm_tag);
|
||||
|
||||
mutex_enter(ec->ec_lock);
|
||||
SIMPLEQ_FOREACH_SAFE(vlanidp, &ec->ec_vids, vid_list, tmpp) {
|
||||
if (vlanidp->vid == vid) {
|
||||
SIMPLEQ_REMOVE(&ec->ec_vids, vlanidp,
|
||||
vlanid_list, vid_list);
|
||||
kmem_free(vlanidp, sizeof(*vlanidp));
|
||||
}
|
||||
}
|
||||
mutex_exit(ec->ec_lock);
|
||||
if (ec->ec_vlan_cb != NULL)
|
||||
(void)(*ec->ec_vlan_cb)(ec, vid, false);
|
||||
if (--ec->ec_nvlans == 0) {
|
||||
IFNET_LOCK(p);
|
||||
(void)ether_disable_vlan_mtu(p);
|
||||
@ -999,6 +1035,7 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, void *data)
|
||||
error = ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
error = vlan_config(ifv, pr, vlr.vlr_tag);
|
||||
if (error != 0)
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user