Skip to content
Permalink
Browse files

OS-2340 vnics should support LSO

OS-6778 MAC loopback traffic should avoid cksum work
OS-6794 want LSO support in viona
OS-7319 dangling ref in mac_sw_cksum()
OS-7331 mac_sw_cksum() drops valid UDP traffic
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
  • Loading branch information
rzezeski committed Oct 26, 2018
1 parent 6382b25 commit e6151003c8efce19988229b39ba3dbb5551dc6f1
@@ -57,6 +57,7 @@
#include <sys/vtrace.h>
#include <sys/isa_defs.h>
#include <sys/mac.h>
#include <sys/mac_client.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/route.h>
@@ -659,11 +660,13 @@ ill_input_short_v4(mblk_t *mp, void *iph_arg, void *nexthop_arg,
}

/*
* If there is a good HW IP header checksum we clear the need
* If the packet originated from a same-machine sender or
* there is a good HW IP header checksum, we clear the need
* look at the IP header checksum.
*/
if ((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) &&
ILL_HCKSUM_CAPABLE(ill) && dohwcksum) {
if ((DB_CKSUMFLAGS(mp) & HW_LOCAL_MAC) ||
((DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) &&
ILL_HCKSUM_CAPABLE(ill) && dohwcksum)) {
/* Header checksum was ok. Clear the flag */
DB_CKSUMFLAGS(mp) &= ~HCK_IPV4_HDRCKSUM;
ira->ira_flags &= ~IRAF_VERIFY_IP_CKSUM;
@@ -2256,12 +2259,13 @@ ip_input_cksum_v4(iaflags_t iraflags, mblk_t *mp, ipha_t *ipha,
* We apply this for all ULP protocols. Does the HW know to
* not set the flags for SCTP and other protocols.
*/

hck_flags = DB_CKSUMFLAGS(mp);

if (hck_flags & HCK_FULLCKSUM_OK) {
if ((hck_flags & HCK_FULLCKSUM_OK) || (hck_flags & HW_LOCAL_MAC)) {
/*
* Hardware has already verified the checksum.
* Either the hardware already verified the checksum
* or the packet is from a same-machine sender in
* which case we assume data integrity.
*/
return (B_TRUE);
}
@@ -21,6 +21,7 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2018 Joyent, Inc.
*/

#ifndef _INET_IP_IMPL_H
@@ -159,9 +160,27 @@ extern "C" {
#define ILL_DIRECT_CAPABLE(ill) \
(((ill)->ill_capabilities & ILL_CAPAB_DLD_DIRECT) != 0)

/* This macro is used by the mac layer */
/*
* Determine if a mblk needs to take the "slow path", aka OTH
* softring. There are multiple reasons why a mblk might take the slow
* path.
*
* o The mblk is not a data message.
*
* o There is more than one outstanding reference to the mblk and it
* does not originate from a local MAC client. If the mblk does
* originate from a local MAC then allow it to pass through with
* more than one reference and leave the copying up to the consumer.
*
* o The IP header is not aligned (we assume alignment in the checksum
* routine).
*
* o The mblk doesn't contain enough data to populate a simple IP header.
*/
#define MBLK_RX_FANOUT_SLOWPATH(mp, ipha) \
(DB_TYPE(mp) != M_DATA || DB_REF(mp) != 1 || !OK_32PTR(ipha) || \
(DB_TYPE(mp) != M_DATA || \
(DB_REF(mp) != 1 && ((DB_CKSUMFLAGS(mp) & HW_LOCAL_MAC) == 0)) || \
!OK_32PTR(ipha) || \
(((uchar_t *)ipha + IP_SIMPLE_HDR_LENGTH) >= (mp)->b_wptr))

/*
@@ -23,6 +23,7 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2016 by Delphix. All rights reserved.
* Copyright 2018 Joyent, Inc.
*/

/*
@@ -41,6 +42,7 @@
#include <sys/modctl.h>
#include <sys/note.h>
#include <sys/param.h>
#include <sys/pattr.h>
#include <sys/policy.h>
#include <sys/sdt.h>
#include <sys/stat.h>
@@ -1692,7 +1694,8 @@ bridge_learn(bridge_link_t *blp, const uint8_t *saddr, uint16_t ingress_nick,
* The passed-in tci is the "impossible" value 0xFFFF when no tag is present.
*/
static mblk_t *
reform_vlan_header(mblk_t *mp, uint16_t vlanid, uint16_t tci, uint16_t pvid)
reform_vlan_header(mblk_t *mp, uint16_t vlanid, uint16_t tci, uint16_t pvid,
boolean_t keep_flags)
{
boolean_t source_has_tag = (tci != 0xFFFF);
mblk_t *mpcopy;
@@ -1704,8 +1707,13 @@ reform_vlan_header(mblk_t *mp, uint16_t vlanid, uint16_t tci, uint16_t pvid)
if (mp == NULL)
return (mp);

/* No forwarded packet can have hardware checksum enabled */
DB_CKSUMFLAGS(mp) = 0;
/*
* A forwarded packet cannot have HW offloads enabled unless
* the destination is known to be local to the host and HW
* offloads haven't been emulated.
*/
if (!keep_flags)
DB_CKSUMFLAGS(mp) = 0;

/* Get the no-modification cases out of the way first */
if (!source_has_tag && vlanid == pvid) /* 1a */
@@ -1906,17 +1914,46 @@ bridge_forward(bridge_link_t *blp, mac_header_info_t *hdr_info, mblk_t *mp,
blp->bl_trillthreads++;
mutex_exit(&blp->bl_trilllock);
update_header(mp, hdr_info, B_FALSE);
if (is_xmit)
mp = mac_fix_cksum(mp);
/* all trill data frames have Inner.VLAN */
mp = reform_vlan_header(mp, vlanid, tci, 0);
if (mp == NULL) {
KIINCR(bki_drops);
fwd_unref(bfp);
return (NULL);

if (is_xmit) {
mac_hw_emul(&mp, NULL, NULL,
MAC_HWCKSUM_EMUL | MAC_LSO_EMUL);

if (mp == NULL) {
KIINCR(bki_drops);
goto done;
}
}
trill_encap_fn(tdp, blp, hdr_info, mp,
bfp->bf_trill_nick);

while (mp != NULL) {
mblk_t *next = mp->b_next;

mp->b_next = NULL;

/*
* All trill data frames have
* Inner.VLAN.
*/
mp = reform_vlan_header(mp, vlanid, tci,
0, B_FALSE);

if (mp == NULL) {
/*
* Make sure to free
* any remaining
* segments.
*/
freemsgchain(next);
KIINCR(bki_drops);
goto done;
}

trill_encap_fn(tdp, blp, hdr_info, mp,
bfp->bf_trill_nick);
mp = next;
}

done:
mutex_enter(&blp->bl_trilllock);
if (--blp->bl_trillthreads == 0 &&
blp->bl_trilldata == NULL)
@@ -1958,31 +1995,68 @@ bridge_forward(bridge_link_t *blp, mac_header_info_t *hdr_info, mblk_t *mp,
mpsend = copymsg(mp);
}

if (!from_trill && is_xmit)
mpsend = mac_fix_cksum(mpsend);
/*
* If the destination is not local to the host
* then we need to emulate HW offloads because
* we can't guarantee the forwarding
* destination provides them.
*/
if (!from_trill && is_xmit &&
!(bfp->bf_flags & BFF_LOCALADDR)) {
mac_hw_emul(&mpsend, NULL, NULL,
MAC_HWCKSUM_EMUL | MAC_LSO_EMUL);

mpsend = reform_vlan_header(mpsend, vlanid, tci,
blpsend->bl_pvid);
if (mpsend == NULL) {
KIINCR(bki_drops);
continue;
if (mpsend == NULL) {
KIINCR(bki_drops);
continue;
}
}

/*
* The HW emulation above may have segmented
* an LSO mblk.
*/
while ((mpsend != NULL) &&
!(bfp->bf_flags & BFF_LOCALADDR)) {
mblk_t *next = mpsend->b_next;

mpsend->b_next = NULL;
mpsend = reform_vlan_header(mpsend, vlanid, tci,
blpsend->bl_pvid, B_FALSE);

if (mpsend == NULL) {
KIINCR(bki_drops);
mpsend = next;
continue;
}

KIINCR(bki_forwards);
KLPINCR(blpsend, bkl_xmit);
MAC_RING_TX(blpsend->bl_mh, NULL, mpsend,
mpsend);
freemsg(mpsend);
mpsend = next;
}

KIINCR(bki_forwards);
/*
* No need to bump up the link reference count, as
* the forwarding entry itself holds a reference to
* the link.
*/
if (bfp->bf_flags & BFF_LOCALADDR) {
mpsend = reform_vlan_header(mpsend, vlanid, tci,
blpsend->bl_pvid, B_TRUE);

if (mpsend == NULL) {
KIINCR(bki_drops);
continue;
}

KIINCR(bki_forwards);
mac_rx_common(blpsend->bl_mh, NULL, mpsend);
} else {
KLPINCR(blpsend, bkl_xmit);
MAC_RING_TX(blpsend->bl_mh, NULL, mpsend,
mpsend);
freemsg(mpsend);
}
}

/*
* Handle a special case: if we're transmitting to the original
* link, then check whether the localaddr flag is set. If it
@@ -2018,7 +2092,7 @@ bridge_forward(bridge_link_t *blp, mac_header_info_t *hdr_info, mblk_t *mp,
* Inner.VLAN
*/
mpsend = reform_vlan_header(mpsend,
vlanid, tci, 0);
vlanid, tci, 0, B_FALSE);
if (mpsend == NULL) {
KIINCR(bki_drops);
} else {
@@ -2069,25 +2143,57 @@ bridge_forward(bridge_link_t *blp, mac_header_info_t *hdr_info, mblk_t *mp,
mpsend = copymsg(mp);
}

if (!from_trill && is_xmit)
mpsend = mac_fix_cksum(mpsend);
/*
* In this case, send to all links connected
* to the bridge. Some of these destinations
* may not provide HW offload -- so just
* emulate it here.
*/
if (!from_trill && is_xmit) {
mac_hw_emul(&mpsend, NULL, NULL,
MAC_HWCKSUM_EMUL | MAC_LSO_EMUL);

mpsend = reform_vlan_header(mpsend, vlanid, tci,
blpsend->bl_pvid);
if (mpsend == NULL) {
KIINCR(bki_drops);
continue;
if (mpsend == NULL) {
KIINCR(bki_drops);
continue;
}
}

/*
* The HW emulation above may have segmented
* an LSO mblk.
*/
while (mpsend != NULL) {
mblk_t *next = mpsend->b_next;

mpsend->b_next = NULL;
mpsend = reform_vlan_header(mpsend, vlanid, tci,
blpsend->bl_pvid, B_FALSE);

if (mpsend == NULL) {
KIINCR(bki_drops);
mpsend = next;
continue;
}

if (hdr_info->mhi_dsttype ==
MAC_ADDRTYPE_UNICAST)
KIINCR(bki_unknown);
else
KIINCR(bki_mbcast);

KLPINCR(blpsend, bkl_xmit);
if ((mpcopy = copymsg(mpsend)) != NULL) {
mac_rx_common(blpsend->bl_mh, NULL,
mpcopy);
}

MAC_RING_TX(blpsend->bl_mh, NULL, mpsend,
mpsend);
freemsg(mpsend);
mpsend = next;
}

if (hdr_info->mhi_dsttype == MAC_ADDRTYPE_UNICAST)
KIINCR(bki_unknown);
else
KIINCR(bki_mbcast);
KLPINCR(blpsend, bkl_xmit);
if ((mpcopy = copymsg(mpsend)) != NULL)
mac_rx_common(blpsend->bl_mh, NULL, mpcopy);
MAC_RING_TX(blpsend->bl_mh, NULL, mpsend, mpsend);
freemsg(mpsend);
link_unref(blpsend);
}
}

0 comments on commit e615100

Please sign in to comment.
You can’t perform that action at this time.