4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/types.h>
28 #include <sys/atomic.h>
29 #include <sys/pattr.h>
30 #include <netinet/in.h>
31 #include <netinet/ip6.h>
32 #include <inet/common.h>
35 #include <ipp/dscpmk/dscpmk_impl.h>
37 /* Module to mark the ToS/DS field for a given packet */
43 * Given a packet, this routine marks the ToS or DSCP for IPv4 and IPv6 resp.
44 * using the configured dscp_map.
45 * Note that this module does not change the ECN bits.
48 dscpmk_process(mblk_t
**mpp
, dscpmk_data_t
*dscpmk_data
, ip_proc_t proc
)
53 uint8_t dscp
, new_dscp
;
56 ASSERT((mpp
!= NULL
) && (*mpp
!= NULL
));
60 * The action module will receive an M_DATA or an M_CTL followed
61 * by an M_DATA. In the latter case skip the M_CTL.
63 if (mp
->b_datap
->db_type
!= M_DATA
) {
64 if ((mp
->b_cont
!= NULL
) &&
65 (mp
->b_cont
->b_datap
->db_type
== M_DATA
)) {
68 dscpmk0dbg(("dscpmk_process: no data\n"));
69 atomic_inc_64(&dscpmk_data
->epackets
);
75 if ((mp
->b_wptr
- mp
->b_rptr
) < IP_SIMPLE_HDR_LENGTH
) {
76 if (!pullupmsg(mp
, IP_SIMPLE_HDR_LENGTH
)) {
77 dscpmk0dbg(("dscpmk_process: pullup failed\n"));
78 atomic_inc_64(&dscpmk_data
->epackets
);
82 ipha
= (ipha_t
*)mp
->b_rptr
;
84 /* Update global stats */
85 atomic_inc_64(&dscpmk_data
->npackets
);
88 * This should only be called for outgoing packets. For inbound packets
89 * proceed with the next action.
91 if ((proc
== IPP_LOCAL_IN
) || (proc
== IPP_FWD_IN
)) {
92 dscpmk2dbg(("dscpmk_process: cannot mark incoming packets\n"));
93 atomic_inc_64(&dscpmk_data
->ipackets
);
97 /* Figure out the ToS or the Traffic Class from the message */
98 if (IPH_HDR_VERSION(ipha
) == IPV4_VERSION
) {
99 dscp
= ipha
->ipha_type_of_service
;
102 ip6_hdr
= (ip6_t
*)mp
->b_rptr
;
103 dscp
= __IPV6_TCLASS_FROM_FLOW(ip6_hdr
->ip6_vcf
);
108 * Select the new dscp from the dscp_map after ignoring the
109 * ECN/CU from dscp (hence dscp >> 2). new_dscp will be the
112 new_dscp
= dscpmk_data
->dscp_map
[dscp
>> 2];
114 /* Update stats for this new_dscp */
115 atomic_inc_64(&dscpmk_data
->dscp_stats
[new_dscp
].npackets
);
118 * if new_dscp is same as the original, update stats and
121 if (new_dscp
== (dscp
>> 2)) {
122 atomic_inc_64(&dscpmk_data
->unchanged
);
126 /* Get back the ECN/CU value from the original dscp */
127 new_dscp
= (new_dscp
<< 2) | (dscp
& 0x3);
129 atomic_inc_64(&dscpmk_data
->changed
);
131 * IPv4 : ToS structure -- RFC 791
134 * +---+---+---+---+---+---+---+---+
135 * | IP Precd | D | T | R | 0 | 0 |
137 * +---+---+---+---+---+---+---+---+
139 * For Backward Compatability the diff serv DSCP will be mapped
140 * to the 3-bits Precedence field. DTR is not supported. Thus,
141 * the following Class Seletor CodePoints are reserved from this
142 * purpose : xxx000; where x is 0 or 1 (note the last 2 bits are
143 * 00) -- see RFC 2474.
147 ipha
->ipha_type_of_service
= new_dscp
;
149 * If the hardware supports checksumming, we don't need
152 if (!(mp
->b_datap
->db_struioun
.cksum
.flags
&
153 HCK_IPV4_HDRCKSUM
)) {
154 ipha
->ipha_hdr_checksum
= 0;
155 ipha
->ipha_hdr_checksum
= ip_csum_hdr(ipha
);
160 * IPv6 : DSCP field structure is as given -- RFC 2474
163 * +---+---+---+---+---+---+---+---+
166 * +---+---+---+---+---+---+---+---+
168 * CU -- Currently Unused
170 * the 32 bit vcf consists of version (4 bits), Traffic class (8 bits)
171 * and flow id (20 bits). Need to take care of Big/Little-Endianess.
174 ip6_hdr
->ip6_vcf
= (ip6_hdr
->ip6_vcf
& TCLASS_MASK
) |
177 ip6_hdr
->ip6_vcf
= (ip6_hdr
->ip6_vcf
& TCLASS_MASK
) |
178 ((new_dscp
>> 4) | ((new_dscp
<< 12) & 0xF000));