4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2017 Joyent, Inc.
25 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 /*
29 * MAC data path
30 *
31 * The MAC data path is concerned with the flow of traffic from mac clients --
32 * DLS, IP, etc. -- to various GLDv3 device drivers -- e1000g, vnic, aggr,
33 * ixgbe, etc. -- and from the GLDv3 device drivers back to clients.
34 *
35 * -----------
36 * Terminology
37 * -----------
38 *
39 * MAC uses a lot of different, but related terms that are associated with the
40 * design and structure of the data path. Before we cover other aspects, first
41 * let's review the terminology that MAC uses.
42 *
43 * MAC
44 *
45 * This driver. It interfaces with device drivers and provides abstractions
1698 * mac_rx_srs_long_fanout
1699 *
1700 * The fanout routine for VLANs, and for anything else that isn't performing
1701 * explicit dls bypass. Returns -1 on an error (drop the packet due to a
1702 * malformed packet), 0 on success, with values written in *indx and *type.
1703 */
1704 static int
1705 mac_rx_srs_long_fanout(mac_soft_ring_set_t *mac_srs, mblk_t *mp,
1706 uint32_t sap, size_t hdrsize, enum pkt_type *type, uint_t *indx)
1707 {
1708 ip6_t *ip6h;
1709 ipha_t *ipha;
1710 uint8_t *whereptr;
1711 uint_t hash;
1712 uint16_t remlen;
1713 uint8_t nexthdr;
1714 uint16_t hdr_len;
1715 uint32_t src_val, dst_val;
1716 boolean_t modifiable = B_TRUE;
1717 boolean_t v6;
1718
1719 ASSERT(MBLKL(mp) >= hdrsize);
1720
1721 if (sap == ETHERTYPE_IPV6) {
1722 v6 = B_TRUE;
1723 hdr_len = IPV6_HDR_LEN;
1724 } else if (sap == ETHERTYPE_IP) {
1725 v6 = B_FALSE;
1726 hdr_len = IP_SIMPLE_HDR_LENGTH;
1727 } else {
1728 *indx = 0;
1729 *type = OTH;
1730 return (0);
1731 }
1732
1733 ip6h = (ip6_t *)(mp->b_rptr + hdrsize);
1734 ipha = (ipha_t *)ip6h;
1735
1736 if ((uint8_t *)ip6h == mp->b_wptr) {
1737 /*
1772 *indx = 0;
1773 *type = OTH;
1774 fanout_unaligned++;
1775 return (0);
1776 }
1777
1778 /*
1779 * Extract next-header, full header length, and source-hash value
1780 * using v4/v6 specific fields.
1781 */
1782 if (v6) {
1783 remlen = ntohs(ip6h->ip6_plen);
1784 nexthdr = ip6h->ip6_nxt;
1785 src_val = V4_PART_OF_V6(ip6h->ip6_src);
1786 dst_val = V4_PART_OF_V6(ip6h->ip6_dst);
1787 /*
1788 * Do src based fanout if below tunable is set to B_TRUE or
1789 * when mac_ip_hdr_length_v6() fails because of malformed
1790 * packets or because mblks need to be concatenated using
1791 * pullupmsg().
1792 *
1793 * Perform a version check to prevent parsing weirdness...
1794 */
1795 if (IPH_HDR_VERSION(ip6h) != IPV6_VERSION ||
1796 !mac_ip_hdr_length_v6(ip6h, mp->b_wptr, &hdr_len, &nexthdr,
1797 NULL)) {
1798 goto src_dst_based_fanout;
1799 }
1800 } else {
1801 hdr_len = IPH_HDR_LENGTH(ipha);
1802 remlen = ntohs(ipha->ipha_length) - hdr_len;
1803 nexthdr = ipha->ipha_protocol;
1804 src_val = (uint32_t)ipha->ipha_src;
1805 dst_val = (uint32_t)ipha->ipha_dst;
1806 /*
1807 * Catch IPv4 fragment case here. IPv6 has nexthdr == FRAG
1808 * for its equivalent case.
1809 */
1810 if ((ntohs(ipha->ipha_fragment_offset_and_flags) &
1811 (IPH_MF | IPH_OFFSET)) != 0) {
1812 goto src_dst_based_fanout;
1813 }
1814 }
1815 if (remlen < MIN_EHDR_LEN)
1816 return (-1);
1817 whereptr = (uint8_t *)ip6h + hdr_len;
1818
1819 /* If the transport is one of below, we do port/SPI based fanout */
1820 switch (nexthdr) {
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2019 Joyent, Inc.
26 */
27
28 /*
29 * MAC data path
30 *
31 * The MAC data path is concerned with the flow of traffic from mac clients --
32 * DLS, IP, etc. -- to various GLDv3 device drivers -- e1000g, vnic, aggr,
33 * ixgbe, etc. -- and from the GLDv3 device drivers back to clients.
34 *
35 * -----------
36 * Terminology
37 * -----------
38 *
39 * MAC uses a lot of different, but related terms that are associated with the
40 * design and structure of the data path. Before we cover other aspects, first
41 * let's review the terminology that MAC uses.
42 *
43 * MAC
44 *
45 * This driver. It interfaces with device drivers and provides abstractions
1698 * mac_rx_srs_long_fanout
1699 *
1700 * The fanout routine for VLANs, and for anything else that isn't performing
1701 * explicit dls bypass. Returns -1 on an error (drop the packet due to a
1702 * malformed packet), 0 on success, with values written in *indx and *type.
1703 */
1704 static int
1705 mac_rx_srs_long_fanout(mac_soft_ring_set_t *mac_srs, mblk_t *mp,
1706 uint32_t sap, size_t hdrsize, enum pkt_type *type, uint_t *indx)
1707 {
1708 ip6_t *ip6h;
1709 ipha_t *ipha;
1710 uint8_t *whereptr;
1711 uint_t hash;
1712 uint16_t remlen;
1713 uint8_t nexthdr;
1714 uint16_t hdr_len;
1715 uint32_t src_val, dst_val;
1716 boolean_t modifiable = B_TRUE;
1717 boolean_t v6;
1718 int errno;
1719
1720 ASSERT(MBLKL(mp) >= hdrsize);
1721
1722 if (sap == ETHERTYPE_IPV6) {
1723 v6 = B_TRUE;
1724 hdr_len = IPV6_HDR_LEN;
1725 } else if (sap == ETHERTYPE_IP) {
1726 v6 = B_FALSE;
1727 hdr_len = IP_SIMPLE_HDR_LENGTH;
1728 } else {
1729 *indx = 0;
1730 *type = OTH;
1731 return (0);
1732 }
1733
1734 ip6h = (ip6_t *)(mp->b_rptr + hdrsize);
1735 ipha = (ipha_t *)ip6h;
1736
1737 if ((uint8_t *)ip6h == mp->b_wptr) {
1738 /*
1773 *indx = 0;
1774 *type = OTH;
1775 fanout_unaligned++;
1776 return (0);
1777 }
1778
1779 /*
1780 * Extract next-header, full header length, and source-hash value
1781 * using v4/v6 specific fields.
1782 */
1783 if (v6) {
1784 remlen = ntohs(ip6h->ip6_plen);
1785 nexthdr = ip6h->ip6_nxt;
1786 src_val = V4_PART_OF_V6(ip6h->ip6_src);
1787 dst_val = V4_PART_OF_V6(ip6h->ip6_dst);
1788 /*
1789 * Do src based fanout if below tunable is set to B_TRUE or
1790 * when mac_ip_hdr_length_v6() fails because of malformed
1791 * packets or because mblks need to be concatenated using
1792 * pullupmsg().
1793 */
1794 errno = mac_ip_hdr_length_v6(ip6h, mp->b_wptr, &hdr_len,
1795 &nexthdr, NULL);
1796 switch (errno) {
1797 case EINVAL:
1798 /* Bad version. */
1799 *indx = 0;
1800 *type = OTH;
1801 return (0);
1802 case 0:
1803 break;
1804 default:
1805 goto src_dst_based_fanout;
1806 }
1807 } else {
1808 if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) {
1809 /* Bad version. */
1810 *indx = 0;
1811 *type = OTH;
1812 return (0);
1813 }
1814 hdr_len = IPH_HDR_LENGTH(ipha);
1815 remlen = ntohs(ipha->ipha_length) - hdr_len;
1816 nexthdr = ipha->ipha_protocol;
1817 src_val = (uint32_t)ipha->ipha_src;
1818 dst_val = (uint32_t)ipha->ipha_dst;
1819 /*
1820 * Catch IPv4 fragment case here. IPv6 has nexthdr == FRAG
1821 * for its equivalent case.
1822 */
1823 if ((ntohs(ipha->ipha_fragment_offset_and_flags) &
1824 (IPH_MF | IPH_OFFSET)) != 0) {
1825 goto src_dst_based_fanout;
1826 }
1827 }
1828 if (remlen < MIN_EHDR_LEN)
1829 return (-1);
1830 whereptr = (uint8_t *)ip6h + hdr_len;
1831
1832 /* If the transport is one of below, we do port/SPI based fanout */
1833 switch (nexthdr) {
|