summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/mac
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/mac')
-rw-r--r--usr/src/uts/common/io/mac/mac.c6
-rw-r--r--usr/src/uts/common/io/mac/mac_client.c35
-rw-r--r--usr/src/uts/common/io/mac/mac_protect.c118
-rw-r--r--usr/src/uts/common/io/mac/mac_stat.c8
4 files changed, 133 insertions, 34 deletions
diff --git a/usr/src/uts/common/io/mac/mac.c b/usr/src/uts/common/io/mac/mac.c
index 41d3ee5fe1..4ce359f87b 100644
--- a/usr/src/uts/common/io/mac/mac.c
+++ b/usr/src/uts/common/io/mac/mac.c
@@ -159,7 +159,7 @@
* perimeter) across a call to any other layer from the mac layer. The call to
* any other layer could be via mi_* entry points, classifier entry points into
* the driver or via upcall pointers into layers above. The mac perimeter may
- * be acquired or held only in the down direction, for e.g. when calling into
+ * be acquired or held only in the down direction, e.g. when calling into
* a mi_* driver enty point to provide atomicity of the operation.
*
* R8. Since it is not guaranteed (see R14) that drivers won't hold locks across
@@ -208,7 +208,7 @@
* number whenever the ring's stop routine is invoked.
* See comments in mac_rx_ring();
*
- * R17 Similarly mi_stop is another synchronization point and the driver must
+ * R17. Similarly mi_stop is another synchronization point and the driver must
* ensure that all upcalls are done and there won't be any future upcall
* before returning from mi_stop.
*
@@ -228,7 +228,7 @@
*
* cpu_lock -> mac_srs_g_lock -> srs_lock -> s_ring_lock [mac_walk_srs_and_bind]
*
- * i_dls_devnet_lock -> mac layer locks [dls_devnet_rename]
+ * mac perim -> i_dls_devnet_lock [dls_devnet_rename]
*
* Perimeters are ordered P1 -> P2 -> P3 from top to bottom in order of mac
* client to driver. In the case of clients that explictly use the mac provided
diff --git a/usr/src/uts/common/io/mac/mac_client.c b/usr/src/uts/common/io/mac/mac_client.c
index 94ad441a65..952b4c844b 100644
--- a/usr/src/uts/common/io/mac/mac_client.c
+++ b/usr/src/uts/common/io/mac/mac_client.c
@@ -3349,6 +3349,11 @@ mac_promisc_add(mac_client_handle_t mch, mac_client_promisc_type_t type,
mac_cb_info_t *mcbi;
int rc;
+ if ((flags & MAC_PROMISC_FLAGS_NO_COPY) &&
+ (flags & MAC_PROMISC_FLAGS_DO_FIXUPS)) {
+ return (EINVAL);
+ }
+
i_mac_perim_enter(mip);
if ((rc = mac_start((mac_handle_t)mip)) != 0) {
@@ -3395,6 +3400,7 @@ mac_promisc_add(mac_client_handle_t mch, mac_client_promisc_type_t type,
mpip->mpi_strip_vlan_tag =
((flags & MAC_PROMISC_FLAGS_VLAN_TAG_STRIP) != 0);
mpip->mpi_no_copy = ((flags & MAC_PROMISC_FLAGS_NO_COPY) != 0);
+ mpip->mpi_do_fixups = ((flags & MAC_PROMISC_FLAGS_DO_FIXUPS) != 0);
mcbi = &mip->mi_promisc_cb_info;
mutex_enter(mcbi->mcbi_lockp);
@@ -4105,13 +4111,33 @@ mac_promisc_dispatch_one(mac_promisc_impl_t *mpip, mblk_t *mp,
{
mblk_t *mp_next;
- if (!mpip->mpi_no_copy || mpip->mpi_strip_vlan_tag) {
+ if (!mpip->mpi_no_copy || mpip->mpi_strip_vlan_tag ||
+ (mpip->mpi_do_fixups && local)) {
mblk_t *mp_copy;
mp_copy = copymsg(mp);
if (mp_copy == NULL)
return;
+ /*
+ * The consumer has requested we emulate HW offloads
+ * for host-local packets.
+ */
+ if (mpip->mpi_do_fixups && local) {
+ /*
+ * Remember that copymsg() doesn't copy
+ * b_next, so we are only passing a single
+ * packet to mac_hw_emul(). Also keep in mind
+ * that mp_copy will become an mblk chain if
+ * the argument is an LSO message.
+ */
+ mac_hw_emul(&mp_copy, NULL, NULL,
+ MAC_HWCKSUM_EMUL | MAC_LSO_EMUL);
+
+ if (mp_copy == NULL)
+ return;
+ }
+
if (mpip->mpi_strip_vlan_tag) {
mp_copy = mac_strip_vlan_tag_chain(mp_copy);
if (mp_copy == NULL)
@@ -4320,16 +4346,15 @@ mac_info_get(const char *name, mac_info_t *minfop)
/*
* To get the capabilities that MAC layer cares about, such as rings, factory
* mac address, vnic or not, it should directly invoke this function. If the
- * link is part of a bridge, then the only "capability" it has is the inability
- * to do zero copy.
+ * link is part of a bridge, then the link is unable to do zero copy.
*/
boolean_t
i_mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- if (mip->mi_bridge_link != NULL) {
- return (cap == MAC_CAPAB_NO_ZCOPY);
+ if (mip->mi_bridge_link != NULL && cap == MAC_CAPAB_NO_ZCOPY) {
+ return (B_TRUE);
} else if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB) {
boolean_t res;
diff --git a/usr/src/uts/common/io/mac/mac_protect.c b/usr/src/uts/common/io/mac/mac_protect.c
index 17959ac48d..cff1f884b9 100644
--- a/usr/src/uts/common/io/mac/mac_protect.c
+++ b/usr/src/uts/common/io/mac/mac_protect.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, Joyent, Inc. All rights reserved.
+ * Copyright 2017, Joyent, Inc. All rights reserved.
*/
/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
@@ -209,7 +209,7 @@ typedef struct slaac_addr {
} slaac_addr_t;
static void start_txn_cleanup_timer(mac_client_impl_t *);
-static boolean_t allowed_ips_set(mac_resource_props_t *, uint32_t);
+static boolean_t dynamic_method_set(mac_protect_t *, uint32_t);
#define BUMP_STAT(m, s) (m)->mci_misc_stat.mms_##s++
@@ -580,8 +580,7 @@ intercept_dhcpv4_outbound(mac_client_impl_t *mcip, ipha_t *ipha, uchar_t *end)
if (get_dhcpv4_info(ipha, end, &dh4) != 0)
return (B_TRUE);
- /* ip_nospoof/allowed-ips and DHCP are mutually exclusive by default */
- if (allowed_ips_set(mrp, IPV4_VERSION))
+ if (!dynamic_method_set(&mrp->mrp_protect, MPT_DYN_DHCPV4))
return (B_FALSE);
if (get_dhcpv4_option(dh4, end, CD_DHCP_TYPE, &opt, &opt_len) != 0 ||
@@ -1310,8 +1309,7 @@ intercept_dhcpv6_outbound(mac_client_impl_t *mcip, ip6_t *ip6h, uchar_t *end)
if (get_dhcpv6_info(ip6h, end, &dh6) != 0)
return (B_TRUE);
- /* ip_nospoof/allowed-ips and DHCP are mutually exclusive by default */
- if (allowed_ips_set(mrp, IPV6_VERSION))
+ if (!dynamic_method_set(&mrp->mrp_protect, MPT_DYN_DHCPV6))
return (B_FALSE);
/*
@@ -1517,6 +1515,10 @@ intercept_ra_inbound(mac_client_impl_t *mcip, ip6_t *ip6h, uchar_t *end,
{
struct nd_opt_hdr *opt;
int len, optlen;
+ mac_protect_t *protect = &MCIP_RESOURCE_PROPS(mcip)->mrp_protect;
+
+ if (!dynamic_method_set(protect, MPT_DYN_SLAAC))
+ return;
if (ip6h->ip6_hlim != 255) {
DTRACE_PROBE1(invalid__hoplimit, uint8_t, ip6h->ip6_hlim);
@@ -1755,6 +1757,7 @@ ipnospoof_check_v4(mac_client_impl_t *mcip, mac_protect_t *protect,
if (*addr == INADDR_ANY)
return (B_TRUE);
+ /* If any specific addresses or subnets are allowed, check them */
for (i = 0; i < protect->mp_ipaddrcnt; i++) {
mac_ipaddr_t *v4addr = &protect->mp_ipaddrs[i];
@@ -1775,14 +1778,19 @@ ipnospoof_check_v4(mac_client_impl_t *mcip, mac_protect_t *protect,
return (B_TRUE);
}
}
- return (protect->mp_ipaddrcnt == 0 ?
- check_dhcpv4_dyn_ip(mcip, *addr) : B_FALSE);
+
+ if (dynamic_method_set(protect, MPT_DYN_DHCPV4)) {
+ return (check_dhcpv4_dyn_ip(mcip, *addr));
+ }
+
+ return (B_FALSE);
}
static boolean_t
ipnospoof_check_v6(mac_client_impl_t *mcip, mac_protect_t *protect,
in6_addr_t *addr)
{
+ boolean_t slaac_enabled, dhcpv6_enabled;
uint_t i;
/*
@@ -1793,7 +1801,7 @@ ipnospoof_check_v6(mac_client_impl_t *mcip, mac_protect_t *protect,
IN6_ARE_ADDR_EQUAL(&mcip->mci_v6_local_addr, addr)))
return (B_TRUE);
-
+ /* If any specific addresses or subnets are allowed, check them */
for (i = 0; i < protect->mp_ipaddrcnt; i++) {
mac_ipaddr_t *v6addr = &protect->mp_ipaddrs[i];
@@ -1804,12 +1812,15 @@ ipnospoof_check_v6(mac_client_impl_t *mcip, mac_protect_t *protect,
return (B_TRUE);
}
- if (protect->mp_ipaddrcnt == 0) {
- return (check_slaac_ip(mcip, addr) ||
- check_dhcpv6_dyn_ip(mcip, addr));
- } else {
- return (B_FALSE);
- }
+ slaac_enabled = dynamic_method_set(protect, MPT_DYN_SLAAC);
+ if (slaac_enabled && check_slaac_ip(mcip, addr))
+ return (B_TRUE);
+
+ dhcpv6_enabled = dynamic_method_set(protect, MPT_DYN_DHCPV6);
+ if (dhcpv6_enabled && check_dhcpv6_dyn_ip(mcip, addr))
+ return (B_TRUE);
+
+ return (B_FALSE);
}
/*
@@ -2025,6 +2036,9 @@ dhcpnospoof_check_cid(mac_protect_t *p, uchar_t *cid, uint_t cidlen)
bcmp(dcid->dc_id, cid, cidlen) == 0)
return (B_TRUE);
}
+
+ DTRACE_PROBE3(missing__cid, mac_protect_t *, p,
+ uchar_t *, cid, uint_t, cidlen);
return (B_FALSE);
}
@@ -2046,6 +2060,12 @@ dhcpnospoof_check_v4(mac_client_impl_t *mcip, mac_protect_t *p,
bcmp(mcip->mci_unicast->ma_addr, dh4->chaddr, maclen) != 0) {
return (B_FALSE);
}
+
+ /* Everything after here is checking the Client Identifier */
+ if (p->mp_allcids == MPT_TRUE) {
+ return (B_TRUE);
+ }
+
if (get_dhcpv4_option(dh4, end, CD_CLIENT_ID, &cid, &optlen) == 0)
cidlen = optlen;
@@ -2082,6 +2102,11 @@ dhcpnospoof_check_v6(mac_client_impl_t *mcip, mac_protect_t *p,
mtype == DHCPV6_MSG_RECONFIGURE)
return (B_TRUE);
+ /* Everything after here is checking the Client Identifier */
+ if (p->mp_allcids == MPT_TRUE) {
+ return (B_TRUE);
+ }
+
d6o = get_dhcpv6_option(&dh6[1], end - (uchar_t *)&dh6[1], NULL,
DHCPV6_OPT_CLIENTID, &cidlen);
if (d6o == NULL || (uchar_t *)d6o + cidlen > end)
@@ -2159,7 +2184,6 @@ dhcpnospoof_check(mac_client_impl_t *mcip, mac_protect_t *protect,
return (0);
fail:
- /* increment dhcpnospoof stat here */
freemsg(nmp);
return (err);
}
@@ -2487,6 +2511,11 @@ mac_protect_validate(mac_resource_props_t *mrp)
if ((err = validate_cids(p)) != 0)
return (err);
+ if (p->mp_allcids != MPT_FALSE && p->mp_allcids != MPT_TRUE &&
+ p->mp_allcids != MPT_RESET) {
+ return (EINVAL);
+ }
+
return (0);
}
@@ -2554,6 +2583,16 @@ mac_protect_update(mac_resource_props_t *new, mac_resource_props_t *curr)
cp->mp_cidcnt = 0;
}
}
+ if (np->mp_allcids == MPT_RESET) {
+ cp->mp_allcids = MPT_FALSE;
+ } else if (np->mp_allcids != 0) {
+ cp->mp_allcids = MPT_TRUE;
+ }
+ if (np->mp_dynamic == MPT_RESET) {
+ cp->mp_dynamic = 0;
+ } else if (np->mp_dynamic != 0) {
+ cp->mp_dynamic = np->mp_dynamic;
+ }
}
void
@@ -2597,15 +2636,50 @@ mac_protect_fini(mac_client_impl_t *mcip)
}
static boolean_t
-allowed_ips_set(mac_resource_props_t *mrp, uint32_t af)
+dynamic_method_set(mac_protect_t *mpt, uint32_t method)
+{
+ if (mpt->mp_dynamic != 0) {
+ return ((mpt->mp_dynamic & method) != 0);
+ } else {
+ return (mpt->mp_ipaddrcnt == 0);
+ }
+}
+
+boolean_t
+mac_protect_check_addr(mac_client_handle_t mch, boolean_t isv6,
+ in6_addr_t *v6addr)
{
- int i;
+ mac_perim_handle_t perim;
+ mac_client_impl_t *mcip = (mac_client_impl_t *)mch;
+ mac_handle_t mh = (mac_handle_t)mcip->mci_mip;
- for (i = 0; i < mrp->mrp_protect.mp_ipaddrcnt; i++) {
- if (mrp->mrp_protect.mp_ipaddrs[i].ip_version == af)
- return (B_TRUE);
+ mac_perim_enter_by_mh(mh, &perim);
+
+ mac_resource_props_t *mrp = MCIP_RESOURCE_PROPS(mcip);
+ mac_protect_t *p;
+ boolean_t allowed;
+
+ ASSERT(mrp != NULL);
+
+ p = &mrp->mrp_protect;
+
+ /* If mac protection/ipnospoof isn't enabled, return true */
+ if ((mrp->mrp_mask & MRP_PROTECT) == 0 ||
+ (p->mp_types & MPT_IPNOSPOOF) == 0) {
+ allowed = B_TRUE;
+ goto done;
}
- return (B_FALSE);
+
+ if (isv6) {
+ allowed = ipnospoof_check_v6(mcip, p, v6addr);
+ } else {
+ in_addr_t *v4addr = &V4_PART_OF_V6((*v6addr));
+ allowed = ipnospoof_check_v4(mcip, p, v4addr);
+ }
+
+done:
+ mac_perim_exit(perim);
+ return (allowed);
}
mac_protect_t *
diff --git a/usr/src/uts/common/io/mac/mac_stat.c b/usr/src/uts/common/io/mac/mac_stat.c
index dbb5c0a914..e1151565a6 100644
--- a/usr/src/uts/common/io/mac/mac_stat.c
+++ b/usr/src/uts/common/io/mac/mac_stat.c
@@ -391,8 +391,8 @@ i_mac_stat_create(void *handle, const char *modname, const char *statname,
kstat_t *ksp;
kstat_named_t *knp;
- ksp = kstat_create(modname, 0, statname, "net",
- KSTAT_TYPE_NAMED, count, 0);
+ ksp = kstat_create_zone(modname, 0, statname, "net",
+ KSTAT_TYPE_NAMED, count, 0, getzoneid());
if (ksp == NULL)
return (NULL);
@@ -949,9 +949,9 @@ mac_driver_stat_create(mac_impl_t *mip)
major_t major = getmajor(mip->mi_phy_dev);
count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount;
- ksp = kstat_create((const char *)ddi_major_to_name(major),
+ ksp = kstat_create_zone((const char *)ddi_major_to_name(major),
getminor(mip->mi_phy_dev) - 1, MAC_KSTAT_NAME,
- MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0);
+ MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0, getzoneid());
if (ksp == NULL)
return;