OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [netinet/] [in_cksum.c] - Blame information for rev 281

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/sys/netinet/in_cksum.c
4
//
5
//==========================================================================
6
//####BSDCOPYRIGHTBEGIN####
7
//
8
// -------------------------------------------
9
//
10
// Portions of this software may have been derived from OpenBSD, 
11
// FreeBSD or other sources, and are covered by the appropriate
12
// copyright disclaimers included herein.
13
//
14
// Portions created by Red Hat are
15
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16
//
17
// -------------------------------------------
18
//
19
//####BSDCOPYRIGHTEND####
20
//==========================================================================
21
 
22
/* $FreeBSD: src/sys/alpha/alpha/in_cksum.c,v 1.2.2.2 2001/05/04 15:36:43 ru Exp $ */
23
/* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */
24
 
25
/*
26
 * Copyright (c) 1988, 1992, 1993
27
 *      The Regents of the University of California.  All rights reserved.
28
 * Copyright (c) 1996
29
 *      Matt Thomas <matt@3am-software.com>
30
 *
31
 * Redistribution and use in source and binary forms, with or without
32
 * modification, are permitted provided that the following conditions
33
 * are met:
34
 * 1. Redistributions of source code must retain the above copyright
35
 *    notice, this list of conditions and the following disclaimer.
36
 * 2. Redistributions in binary form must reproduce the above copyright
37
 *    notice, this list of conditions and the following disclaimer in the
38
 *    documentation and/or other materials provided with the distribution.
39
 * 3. All advertising materials mentioning features or use of this software
40
 *    must display the following acknowledgement:
41
 *      This product includes software developed by the University of
42
 *      California, Berkeley and its contributors.
43
 * 4. Neither the name of the University nor the names of its contributors
44
 *    may be used to endorse or promote products derived from this software
45
 *    without specific prior written permission.
46
 *
47
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57
 * SUCH DAMAGE.
58
 *
59
 *      @(#)in_cksum.c  8.1 (Berkeley) 6/10/93
60
 */
61
 
62
#include <sys/param.h>
63
#include <sys/mbuf.h>
64
#include <netinet/in_systm.h>
65
#include <netinet/in.h>
66
#include <netinet/ip.h>
67
 
68
/*
69
 * Checksum routine for Internet Protocol family headers
70
 *    (Portable Alpha version).
71
 *
72
 * This routine is very heavily used in the network
73
 * code and should be modified for each CPU to be as fast as possible.
74
 */
75
 
76
#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
77
#define REDUCE32                                                          \
78
    {                                                                     \
79
        q_util.q = sum;                                                   \
80
        sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3];       \
81
    }
82
#define REDUCE16                                                          \
83
    {                                                                     \
84
        q_util.q = sum;                                                   \
85
        l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
86
        sum = l_util.s[0] + l_util.s[1];                           \
87
        ADDCARRY(sum);                                                    \
88
    }
89
 
90
static const u_int32_t in_masks[] = {
91
#if BYTE_ORDER == BIG_ENDIAN
92
        /*0 bytes*/ /*1 byte*/  /*2 bytes*/ /*3 bytes*/
93
        0x00000000, 0xFF000000, 0xFFFF0000, 0xFFFFFF00, /* offset 0 */
94
        0x00000000, 0x00FF0000, 0x00FFFF00, 0x00FFFFFF, /* offset 1 */
95
        0x00000000, 0x0000FF00, 0x0000FFFF, 0x0000FFFF, /* offset 2 */
96
        0x00000000, 0x000000FF, 0x000000FF, 0x000000FF, /* offset 3 */
97
#else
98
        /*0 bytes*/ /*1 byte*/  /*2 bytes*/ /*3 bytes*/
99
        0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */
100
        0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */
101
        0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */
102
        0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */
103
#endif
104
};
105
 
106
union l_util {
107
        u_int16_t s[2];
108
        u_int32_t l;
109
};
110
union q_util {
111
        u_int16_t s[4];
112
        u_int32_t l[2];
113
        u_int64_t q;
114
};
115
 
116
u_int64_t       in_cksumdata __P((caddr_t buf, int len));
117
 
118
u_int64_t
119
in_cksumdata(caddr_t buf, int len)
120
{
121
        const u_int32_t *lw = (u_int32_t *) buf;
122
        u_int64_t sum = 0;
123
        u_int64_t prefilled;
124
        int offset;
125
        union q_util q_util;
126
 
127
        if ((3 & (long) lw) == 0 && len == 20) {
128
             sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4];
129
             REDUCE32;
130
             return sum;
131
        }
132
 
133
        if ((offset = 3 & (long) lw) != 0) {
134
                const u_int32_t *masks = in_masks + (offset << 2);
135
                lw = (u_int32_t *) (((long) lw) - offset);
136
                sum = *lw++ & masks[len >= 3 ? 3 : len];
137
                len -= 4 - offset;
138
                if (len <= 0) {
139
                        REDUCE32;
140
                        return sum;
141
                }
142
        }
143
#if 0
144
        /*
145
         * Force to cache line boundary.
146
         */
147
        offset = 32 - (0x1f & (long) lw);
148
        if (offset < 32 && len > offset) {
149
                len -= offset;
150
                if (4 & offset) {
151
                        sum += (u_int64_t) lw[0];
152
                        lw += 1;
153
                }
154
                if (8 & offset) {
155
                        sum += (u_int64_t) lw[0] + lw[1];
156
                        lw += 2;
157
                }
158
                if (16 & offset) {
159
                        sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3];
160
                        lw += 4;
161
                }
162
        }
163
#endif
164
        /*
165
         * access prefilling to start load of next cache line.
166
         * then add current cache line
167
         * save result of prefilling for loop iteration.
168
         */
169
        prefilled = lw[0];
170
        while ((len -= 32) >= 4) {
171
                u_int64_t prefilling = lw[8];
172
                sum += prefilled + lw[1] + lw[2] + lw[3]
173
                        + lw[4] + lw[5] + lw[6] + lw[7];
174
                lw += 8;
175
                prefilled = prefilling;
176
        }
177
        if (len >= 0) {
178
                sum += prefilled + lw[1] + lw[2] + lw[3]
179
                        + lw[4] + lw[5] + lw[6] + lw[7];
180
                lw += 8;
181
        } else {
182
                len += 32;
183
        }
184
        while ((len -= 16) >= 0) {
185
                sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3];
186
                lw += 4;
187
        }
188
        len += 16;
189
        while ((len -= 4) >= 0) {
190
                sum += (u_int64_t) *lw++;
191
        }
192
        len += 4;
193
        if (len > 0)
194
                sum += (u_int64_t) (in_masks[len] & *lw);
195
        REDUCE32;
196
        return sum;
197
}
198
 
199
u_short
200
in_addword(u_short a, u_short b)
201
{
202
        u_int32_t sum = a + b;
203
 
204
        ADDCARRY(sum);
205
        return (sum);
206
}
207
 
208
u_short
209
in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c)
210
{
211
        u_int64_t sum;
212
        union q_util q_util;
213
        union l_util l_util;
214
 
215
        sum = (u_int64_t) a + b + c;
216
        REDUCE16;
217
        return (sum);
218
}
219
 
220
int
221
in_cksum(struct mbuf *m, int len)
222
{
223
        register u_int64_t sum = 0;
224
        register int mlen = 0;
225
        register int clen = 0;
226
        register caddr_t addr;
227
        union q_util q_util;
228
        union l_util l_util;
229
 
230
        for (; m && len; m = m->m_next) {
231
                if (m->m_len == 0)
232
                        continue;
233
                mlen = m->m_len;
234
                if (len < mlen)
235
                        mlen = len;
236
                addr = mtod(m, caddr_t);
237
                if ((clen ^ (long) addr) & 1)
238
                    sum += in_cksumdata(addr, mlen) << 8;
239
                else
240
                    sum += in_cksumdata(addr, mlen);
241
 
242
                clen += mlen;
243
                len -= mlen;
244
        }
245
        REDUCE16;
246
        return (~sum & 0xffff);
247
}
248
 
249
u_short
250
in_cksum_skip(struct mbuf *m, int len, int skip)
251
{
252
        u_int64_t sum = 0;
253
        int mlen = 0;
254
        int clen = 0;
255
        caddr_t addr;
256
        union q_util q_util;
257
        union l_util l_util;
258
 
259
        len -= skip;
260
        for (; skip && m; m = m->m_next) {
261
                if (m->m_len > skip) {
262
                        mlen = m->m_len - skip;
263
                        addr = mtod(m, caddr_t) + skip;
264
                        goto skip_start;
265
                } else {
266
                        skip -= m->m_len;
267
                }
268
        }
269
 
270
        for (; m && len; m = m->m_next) {
271
                if (m->m_len == 0)
272
                        continue;
273
                mlen = m->m_len;
274
                addr = mtod(m, caddr_t);
275
skip_start:
276
                if (len < mlen)
277
                        mlen = len;
278
                if ((clen ^ (long) addr) & 1)
279
                    sum += in_cksumdata(addr, mlen) << 8;
280
                else
281
                    sum += in_cksumdata(addr, mlen);
282
 
283
                clen += mlen;
284
                len -= mlen;
285
        }
286
        REDUCE16;
287
        return (~sum & 0xffff);
288
}
289
 
290
u_int in_cksum_hdr(const struct ip *ip)
291
{
292
    u_int64_t sum = in_cksumdata((caddr_t) ip, sizeof(struct ip));
293
    union q_util q_util;
294
    union l_util l_util;
295
    REDUCE16;
296
    return (~sum & 0xffff);
297
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.