aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ixgbe/if_ixv.c49
-rw-r--r--sys/dev/ixgbe/if_sriov.c116
-rw-r--r--sys/dev/ixgbe/ixgbe.h2
-rw-r--r--sys/dev/ixgbe/ixgbe_sriov.h3
-rw-r--r--sys/dev/ixgbe/ixgbe_vf.c2
5 files changed, 144 insertions, 28 deletions
diff --git a/sys/dev/ixgbe/if_ixv.c b/sys/dev/ixgbe/if_ixv.c
index f5af6a53da49..788dd506669d 100644
--- a/sys/dev/ixgbe/if_ixv.c
+++ b/sys/dev/ixgbe/if_ixv.c
@@ -114,6 +114,7 @@ static void ixv_configure_ivars(struct ixgbe_softc *);
static void ixv_if_enable_intr(if_ctx_t);
static void ixv_if_disable_intr(if_ctx_t);
static void ixv_if_multi_set(if_ctx_t);
+static int ixv_if_promisc_set(if_ctx_t, int);
static void ixv_if_register_vlan(if_ctx_t, u16);
static void ixv_if_unregister_vlan(if_ctx_t, u16);
@@ -174,6 +175,7 @@ static device_method_t ixv_if_methods[] = {
DEVMETHOD(ifdi_queues_free, ixv_if_queues_free),
DEVMETHOD(ifdi_update_admin_status, ixv_if_update_admin_status),
DEVMETHOD(ifdi_multi_set, ixv_if_multi_set),
+ DEVMETHOD(ifdi_promisc_set, ixv_if_promisc_set),
DEVMETHOD(ifdi_mtu_set, ixv_if_mtu_set),
DEVMETHOD(ifdi_media_status, ixv_if_media_status),
DEVMETHOD(ifdi_media_change, ixv_if_media_change),
@@ -847,6 +849,7 @@ ixv_negotiate_api(struct ixgbe_softc *sc)
{
struct ixgbe_hw *hw = &sc->hw;
int mbx_api[] = {
+ ixgbe_mbox_api_13,
ixgbe_mbox_api_12,
ixgbe_mbox_api_11,
ixgbe_mbox_api_10,
@@ -863,6 +866,40 @@ ixv_negotiate_api(struct ixgbe_softc *sc)
return (EINVAL);
} /* ixv_negotiate_api */
+static int
+ixv_update_xcast_mode(struct ixgbe_softc *sc, int flags)
+{
+ if_t ifp;
+ int mode;
+
+ ifp = iflib_get_ifp(sc->ctx);
+ if (flags & IFF_PROMISC)
+ mode = IXGBEVF_XCAST_MODE_PROMISC;
+ else if ((flags & IFF_ALLMULTI) != 0 ||
+ if_llmaddr_count(ifp) > IXGBE_MAX_VF_MC)
+ mode = IXGBEVF_XCAST_MODE_ALLMULTI;
+ else if (if_llmaddr_count(ifp) != 0)
+ mode = IXGBEVF_XCAST_MODE_MULTI;
+ else
+ mode = IXGBEVF_XCAST_MODE_NONE;
+ return (ixgbevf_update_xcast_mode(&sc->hw, mode));
+}
+
+static int
+ixv_if_promisc_set(if_ctx_t ctx, int flags)
+{
+ struct ixgbe_softc *sc;
+ if_t ifp;
+
+ sc = iflib_get_softc(ctx);
+ ifp = iflib_get_ifp(ctx);
+ if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
+ return (0);
+ if (ixv_update_xcast_mode(sc, flags) != IXGBE_SUCCESS)
+ return (EOPNOTSUPP);
+ return (0);
+} /* ixv_if_promisc_set */
+
static u_int
ixv_if_multi_set_cb(void *cb_arg, struct sockaddr_dl *addr, u_int cnt)
@@ -889,7 +926,7 @@ ixv_if_multi_set(if_ctx_t ctx)
struct ixgbe_softc *sc = iflib_get_softc(ctx);
u8 *update_ptr;
if_t ifp = iflib_get_ifp(ctx);
- int mcnt = 0;
+ int error, mcnt = 0;
IOCTL_DEBUGOUT("ixv_if_multi_set: begin");
@@ -899,6 +936,16 @@ ixv_if_multi_set(if_ctx_t ctx)
sc->hw.mac.ops.update_mc_addr_list(&sc->hw, update_ptr, mcnt,
ixv_mc_array_itr, true);
+ error = ixv_update_xcast_mode(sc, if_getflags(ifp));
+ if (mcnt > IXGBE_MAX_VF_MC && error != IXGBE_SUCCESS) {
+ if (!sc->vf_mcast_overflow_warned)
+ device_printf(sc->dev,
+ "PF rejected all-multicast fallback; only %d "
+ "multicast addresses are active\n",
+ IXGBE_MAX_VF_MC);
+ sc->vf_mcast_overflow_warned = true;
+ } else if (mcnt <= IXGBE_MAX_VF_MC)
+ sc->vf_mcast_overflow_warned = false;
} /* ixv_if_multi_set */
/************************************************************************
diff --git a/sys/dev/ixgbe/if_sriov.c b/sys/dev/ixgbe/if_sriov.c
index 2a5fd6a864ee..903ed72d6e2f 100644
--- a/sys/dev/ixgbe/if_sriov.c
+++ b/sys/dev/ixgbe/if_sriov.c
@@ -342,11 +342,11 @@ ixgbe_vf_vlan_record(struct ixgbe_vf *vf, uint16_t tag, bool enable)
}
static void
-ixgbe_vf_configure_default_vlan(struct ixgbe_softc *sc,
- struct ixgbe_vf *vf)
+ixgbe_vf_configure_vmolr(struct ixgbe_softc *sc, struct ixgbe_vf *vf)
{
struct ixgbe_hw *hw;
uint32_t vmolr, vmvir;
+ uint8_t xcast_mode;
uint16_t tag;
hw = &sc->hw;
@@ -354,11 +354,9 @@ ixgbe_vf_configure_default_vlan(struct ixgbe_softc *sc,
vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf->pool));
- /* Do not receive packets that pass inexact filters. */
- vmolr &= ~(IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_ROPE);
-
- /* Disable Multicast Promicuous Mode. */
- vmolr &= ~IXGBE_VMOLR_MPE;
+ vmolr &= ~(IXGBE_VMOLR_UPE | IXGBE_VMOLR_ROMPE |
+ IXGBE_VMOLR_ROPE | IXGBE_VMOLR_MPE | IXGBE_VMOLR_VPE |
+ IXGBE_VMOLR_AUPE);
/* Accept broadcasts. */
vmolr |= IXGBE_VMOLR_BAM;
@@ -376,9 +374,28 @@ ixgbe_vf_configure_default_vlan(struct ixgbe_softc *sc,
/* Tag all traffic with provided vlan tag. */
vmvir = (tag | IXGBE_VMVIR_VLANA_DEFAULT);
}
+
+ xcast_mode = vf->xcast_mode;
+ if ((vf->api_ver == IXGBE_API_VER_UNKNOWN ||
+ vf->api_ver < IXGBE_API_VER_1_2) && vf->num_mc_hashes != 0)
+ xcast_mode = IXGBEVF_XCAST_MODE_MULTI;
+ switch (xcast_mode) {
+ case IXGBEVF_XCAST_MODE_PROMISC:
+ vmolr |= IXGBE_VMOLR_UPE;
+ /* FALLTHROUGH */
+ case IXGBEVF_XCAST_MODE_ALLMULTI:
+ vmolr |= IXGBE_VMOLR_MPE;
+ /* FALLTHROUGH */
+ case IXGBEVF_XCAST_MODE_MULTI:
+ vmolr |= IXGBE_VMOLR_ROMPE;
+ break;
+ case IXGBEVF_XCAST_MODE_NONE:
+ default:
+ break;
+ }
IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf->pool), vmolr);
IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf->pool), vmvir);
-} /* ixgbe_vf_configure_default_vlan */
+} /* ixgbe_vf_configure_vmolr */
static void
ixgbe_vf_clear_vlans(struct ixgbe_softc *sc, struct ixgbe_vf *vf,
@@ -416,7 +433,7 @@ ixgbe_vf_reset_vlan(struct ixgbe_softc *sc, struct ixgbe_vf *vf,
if (error == IXGBE_SUCCESS)
ixgbe_vf_vlan_record(vf, vf->default_vlan, true);
}
- ixgbe_vf_configure_default_vlan(sc, vf);
+ ixgbe_vf_configure_vmolr(sc, vf);
return (error);
}
@@ -472,15 +489,15 @@ ixgbe_process_vf_reset(struct ixgbe_softc *sc, struct ixgbe_vf *vf)
bool rebuild_mta;
s32 error;
+ rebuild_mta = vf->num_mc_hashes != 0;
+ vf->xcast_mode = IXGBEVF_XCAST_MODE_NONE;
+ vf->num_mc_hashes = 0;
+ bzero(vf->mc_hash, sizeof(vf->mc_hash));
error = ixgbe_vf_reset_vlan(sc, vf, true);
if (error != IXGBE_SUCCESS)
device_printf(sc->dev,
"VF %u default VLAN restore failed: %d\n",
vf->pool, error);
-
- rebuild_mta = vf->num_mc_hashes != 0;
- vf->num_mc_hashes = 0;
- bzero(vf->mc_hash, sizeof(vf->mc_hash));
if (rebuild_mta)
ixgbe_iov_rebuild_mta(sc);
@@ -609,24 +626,21 @@ ixgbe_vf_set_mc_addr(struct ixgbe_softc *sc, struct ixgbe_vf *vf, u32 *msg)
{
u16 *list = (u16*)&msg[1];
int entries;
- u32 vmolr;
- entries = (msg[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
+ entries = (msg[0] & IXGBE_VT_MSGINFO_MASK) >>
+ IXGBE_VT_MSGINFO_SHIFT;
entries = min(entries, IXGBE_MAX_VF_MC);
- vmolr = IXGBE_READ_REG(&sc->hw, IXGBE_VMOLR(vf->pool));
- vmolr &= ~IXGBE_VMOLR_ROMPE;
- IXGBE_WRITE_REG(&sc->hw, IXGBE_VMOLR(vf->pool), vmolr);
-
bzero(vf->mc_hash, sizeof(vf->mc_hash));
bcopy(list, vf->mc_hash, entries * sizeof(*list));
vf->num_mc_hashes = entries;
+ if (entries != 0 && vf->xcast_mode == IXGBEVF_XCAST_MODE_NONE)
+ vf->xcast_mode = IXGBEVF_XCAST_MODE_MULTI;
+ else if (entries == 0 &&
+ vf->xcast_mode == IXGBEVF_XCAST_MODE_MULTI)
+ vf->xcast_mode = IXGBEVF_XCAST_MODE_NONE;
ixgbe_iov_rebuild_mta(sc);
-
- if (entries != 0) {
- vmolr |= IXGBE_VMOLR_ROMPE;
- IXGBE_WRITE_REG(&sc->hw, IXGBE_VMOLR(vf->pool), vmolr);
- }
+ ixgbe_vf_configure_vmolr(sc, vf);
ixgbe_send_vf_success(sc, vf, msg[0]);
} /* ixgbe_vf_set_mc_addr */
@@ -730,6 +744,8 @@ ixgbe_vf_api_negotiate(struct ixgbe_softc *sc, struct ixgbe_vf *vf,
switch (msg[1]) {
case IXGBE_API_VER_1_0:
case IXGBE_API_VER_1_1:
+ case IXGBE_API_VER_1_2:
+ case IXGBE_API_VER_1_3:
vf->api_ver = msg[1];
ixgbe_send_vf_success(sc, vf, msg[0]);
break;
@@ -740,6 +756,47 @@ ixgbe_vf_api_negotiate(struct ixgbe_softc *sc, struct ixgbe_vf *vf,
}
} /* ixgbe_vf_api_negotiate */
+static void
+ixgbe_vf_update_xcast_mode(struct ixgbe_softc *sc, struct ixgbe_vf *vf,
+ uint32_t *msg)
+{
+ struct ixgbe_hw *hw;
+ uint32_t mode;
+
+ hw = &sc->hw;
+ mode = msg[1];
+ switch (vf->api_ver) {
+ case IXGBE_API_VER_1_2:
+ if (mode == IXGBEVF_XCAST_MODE_PROMISC)
+ goto failure;
+ break;
+ case IXGBE_API_VER_1_3:
+ break;
+ default:
+ goto failure;
+ }
+ if (mode > IXGBEVF_XCAST_MODE_PROMISC)
+ goto failure;
+ if (mode > IXGBEVF_XCAST_MODE_MULTI &&
+ !(vf->flags & IXGBE_VF_ALLOW_PROMISC))
+ goto failure;
+ if (mode == IXGBEVF_XCAST_MODE_PROMISC &&
+ (hw->mac.type <= ixgbe_mac_82599EB ||
+ !(IXGBE_READ_REG(hw, IXGBE_FCTRL) & IXGBE_FCTRL_UPE)))
+ goto failure;
+
+ vf->xcast_mode = mode;
+ ixgbe_vf_configure_vmolr(sc, vf);
+ msg[0] &= IXGBE_VT_MSG_MASK;
+ msg[0] |= IXGBE_VT_MSGTYPE_SUCCESS | IXGBE_VT_MSGTYPE_CTS;
+ msg[1] = mode;
+ ixgbe_write_mbx(hw, msg, 2, vf->pool);
+ return;
+
+failure:
+ ixgbe_send_vf_failure(sc, vf, msg[0]);
+} /* ixgbe_vf_update_xcast_mode */
+
static void
ixgbe_vf_get_queues(struct ixgbe_softc *sc, struct ixgbe_vf *vf,
@@ -824,6 +881,9 @@ ixgbe_process_vf_msg(if_ctx_t ctx, struct ixgbe_vf *vf)
case IXGBE_VF_GET_QUEUES:
ixgbe_vf_get_queues(sc, vf, msg);
break;
+ case IXGBE_VF_UPDATE_XCAST_MODE:
+ ixgbe_vf_update_xcast_mode(sc, vf, msg);
+ break;
default:
ixgbe_send_vf_failure(sc, vf, msg[0]);
}
@@ -982,11 +1042,13 @@ ixgbe_init_vf(struct ixgbe_softc *sc, struct ixgbe_vf *vf)
pfmbimr |= IXGBE_VF_BIT(vf->pool);
IXGBE_WRITE_REG(hw, IXGBE_PFMBIMR(vf_index), pfmbimr);
+ vf->xcast_mode = IXGBEVF_XCAST_MODE_NONE;
+ vf->api_ver = IXGBE_API_VER_UNKNOWN;
+ vf->num_mc_hashes = 0;
+ bzero(vf->mc_hash, sizeof(vf->mc_hash));
error = ixgbe_vf_reset_vlan(sc, vf, false);
if (error != IXGBE_SUCCESS)
return (error);
- vf->num_mc_hashes = 0;
- bzero(vf->mc_hash, sizeof(vf->mc_hash));
if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) {
ixgbe_set_rar(&sc->hw, vf->rar_index,
@@ -1114,6 +1176,8 @@ ixgbe_if_iov_vf_add(if_ctx_t ctx, u16 vfnum, const nvlist_t *config)
ixgbe_update_max_frame(sc, vf->maximum_frame_size);
if (nvlist_get_bool(config, "mac-anti-spoof"))
vf->flags |= IXGBE_VF_ANTI_SPOOF;
+ if (nvlist_get_bool(config, "allow-promisc"))
+ vf->flags |= IXGBE_VF_ALLOW_PROMISC;
if (nvlist_exists_binary(config, "mac-addr")) {
mac = nvlist_get_binary(config, "mac-addr", NULL);
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
index 26513a0ba965..330d1a8a2cb3 100644
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -357,6 +357,7 @@ struct ixgbe_vf {
uint16_t num_vlans;
uint16_t default_vlan;
uint16_t api_ver;
+ uint8_t xcast_mode;
};
/* Our softc structure */
@@ -397,6 +398,7 @@ struct ixgbe_softc {
* to repopulate it.
*/
u32 shadow_vfta[IXGBE_VFTA_SIZE];
+ bool vf_mcast_overflow_warned;
/* Info about the interface */
int advertise; /* link speeds */
diff --git a/sys/dev/ixgbe/ixgbe_sriov.h b/sys/dev/ixgbe/ixgbe_sriov.h
index bae3f25f7d71..491a708b6f41 100644
--- a/sys/dev/ixgbe/ixgbe_sriov.h
+++ b/sys/dev/ixgbe/ixgbe_sriov.h
@@ -48,6 +48,7 @@
#define IXGBE_VF_CAP_VLAN (1 << 2) /* VF is permitted to join vlans. */
#define IXGBE_VF_ACTIVE (1 << 3) /* VF is active. */
#define IXGBE_VF_ANTI_SPOOF (1 << 4) /* Enforce source identity. */
+#define IXGBE_VF_ALLOW_PROMISC (1 << 5) /* VF may request promiscuity. */
#define IXGBE_VF_INDEX(vmdq) ((vmdq) / 32)
#define IXGBE_VF_BIT(vmdq) (1 << ((vmdq) % 32))
@@ -61,6 +62,8 @@
#define IXGBE_API_VER_1_0 0
#define IXGBE_API_VER_2_0 1 /* Solaris API. Not supported. */
#define IXGBE_API_VER_1_1 2
+#define IXGBE_API_VER_1_2 3
+#define IXGBE_API_VER_1_3 4
#define IXGBE_API_VER_UNKNOWN UINT16_MAX
#define IXGBE_NO_VM 0
diff --git a/sys/dev/ixgbe/ixgbe_vf.c b/sys/dev/ixgbe/ixgbe_vf.c
index 89bf5929260d..5f65ee038753 100644
--- a/sys/dev/ixgbe/ixgbe_vf.c
+++ b/sys/dev/ixgbe/ixgbe_vf.c
@@ -411,7 +411,7 @@ s32 ixgbe_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list,
DEBUGOUT1("MC Addr Count = %d\n", mc_addr_count);
- cnt = (mc_addr_count > 30) ? 30 : mc_addr_count;
+ cnt = min(mc_addr_count, IXGBE_MAX_VF_MC);
msgbuf[0] = IXGBE_VF_SET_MULTICAST;
msgbuf[0] |= cnt << IXGBE_VT_MSGINFO_SHIFT;