FreeBSD Bugzilla – Attachment 5653 Details for
Bug 13374
PATCH: IPX checksuming code doesn't work at all
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 11.32 KB, created by
bp
on 1999-08-25 11:30:00 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
bp
Created:
1999-08-25 11:30:00 UTC
Size:
11.32 KB
patch
obsolete
>diff -u org/ipx.h ./ipx.h >--- org/ipx.h Mon Feb 16 00:00:00 1998 >+++ ./ipx.h Wed Aug 25 12:15:04 1999 >@@ -95,6 +95,7 @@ > #define SO_ALL_PACKETS 7 > #define SO_MTU 8 > #define SO_IPXTUN_ROUTE 9 >+#define SO_IPX_CHECKSUM 10 > > /* > * IPX addressing >diff -u org/ipx_cksum.c ./ipx_cksum.c >--- org/ipx_cksum.c Mon Feb 16 00:00:00 1998 >+++ ./ipx_cksum.c Wed Aug 25 16:58:24 1999 >@@ -38,173 +38,76 @@ > > #include <sys/param.h> > #include <sys/mbuf.h> >+#include <sys/libkern.h> > >+#include <netipx/ipx.h> > #include <netipx/ipx_var.h> > >-/* >- * Checksum routine for Network Systems Protocol Packets (Big-Endian). >- * >- * This routine is very heavily used in the network >- * code and should be modified for each CPU to be as fast as possible. >- */ > >-#define ADDCARRY(x) { if ((x) > 65535) (x) -= 65535; } >-#define FOLD(x) {l_util.l = (x); (x) = l_util.s[0] + l_util.s[1]; ADDCARRY(x);} >+#define SUMADV sum += *w++ > > u_short >-ipx_cksum(m, len) >- struct mbuf *m; >- int len; >-{ >- register u_short *w; >- register int sum = 0; >- register int mlen = 0; >- register int sum2; >- >+ipx_cksum(struct mbuf *m, int len) { >+ u_int32_t sum = 0; >+ u_short *w; >+ u_char oldtc; >+ int mlen, words; >+ struct ipx *ipx; > union { >- u_short s[2]; >- long l; >- } l_util; >- >- for (;m != NULL && len; m = m->m_next) { >- if (m->m_len == 0) >- continue; >- /* >- * Each trip around loop adds in >- * word from one mbuf segment. >- */ >- w = mtod(m, u_short *); >- if (mlen == -1) { >- /* >- * There is a byte left from the last segment; >- * ones-complement add it into the checksum. >- */ >-#if BYTE_ORDER == BIG_ENDIAN >- sum += *(u_char *)w; >-#else >- sum += *(u_char *)w << 8; >-#endif >- sum += sum; >- w = (u_short *)(1 + (char *)w); >- mlen = m->m_len - 1; >- len--; >- FOLD(sum); >- } else >- mlen = m->m_len; >- if (len < mlen) >- mlen = len; >- len -= mlen; >- /* >- * We can do a 16 bit ones complement sum using >- * 32 bit arithmetic registers for adding, >- * with carries from the low added >- * into the high (by normal carry-chaining) >- * so long as we fold back before 16 carries have occured. >- */ >- if (1 & (int) w) >- goto uuuuglyy; >-#ifndef TINY >-/* -DTINY reduces the size from 1250 to 550, but slows it down by 22% */ >- while ((mlen -= 32) >= 0) { >- sum += w[0]; sum += sum; sum += w[1]; sum += sum; >- sum += w[2]; sum += sum; sum += w[3]; sum += sum; >- sum += w[4]; sum += sum; sum += w[5]; sum += sum; >- sum += w[6]; sum += sum; sum += w[7]; sum += sum; >- FOLD(sum); >- sum += w[8]; sum += sum; sum += w[9]; sum += sum; >- sum += w[10]; sum += sum; sum += w[11]; sum += sum; >- sum += w[12]; sum += sum; sum += w[13]; sum += sum; >- sum += w[14]; sum += sum; sum += w[15]; sum += sum; >- FOLD(sum); >- w += 16; >- } >- mlen += 32; >-#endif >- while ((mlen -= 8) >= 0) { >- sum += w[0]; sum += sum; sum += w[1]; sum += sum; >- sum += w[2]; sum += sum; sum += w[3]; sum += sum; >- FOLD(sum); >- w += 4; >- } >- mlen += 8; >- while ((mlen -= 2) >= 0) { >- sum += *w++; sum += sum; >- } >- goto commoncase; >-uuuuglyy: >-#if BYTE_ORDER == BIG_ENDIAN >-#define ww(n) (((u_char *)w)[n + n + 1]) >-#define vv(n) (((u_char *)w)[n + n]) >-#else >-#if BYTE_ORDER == LITTLE_ENDIAN >-#define vv(n) (((u_char *)w)[n + n + 1]) >-#define ww(n) (((u_char *)w)[n + n]) >-#endif >-#endif >- sum2 = 0; >-#ifndef TINY >- while ((mlen -= 32) >= 0) { >- sum += ww(0); sum += sum; sum += ww(1); sum += sum; >- sum += ww(2); sum += sum; sum += ww(3); sum += sum; >- sum += ww(4); sum += sum; sum += ww(5); sum += sum; >- sum += ww(6); sum += sum; sum += ww(7); sum += sum; >- FOLD(sum); >- sum += ww(8); sum += sum; sum += ww(9); sum += sum; >- sum += ww(10); sum += sum; sum += ww(11); sum += sum; >- sum += ww(12); sum += sum; sum += ww(13); sum += sum; >- sum += ww(14); sum += sum; sum += ww(15); sum += sum; >- FOLD(sum); >- sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2; >- sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2; >- sum2 += vv(4); sum2 += sum2; sum2 += vv(5); sum2 += sum2; >- sum2 += vv(6); sum2 += sum2; sum2 += vv(7); sum2 += sum2; >- FOLD(sum2); >- sum2 += vv(8); sum2 += sum2; sum2 += vv(9); sum2 += sum2; >- sum2 += vv(10); sum2 += sum2; sum2 += vv(11); sum2 += sum2; >- sum2 += vv(12); sum2 += sum2; sum2 += vv(13); sum2 += sum2; >- sum2 += vv(14); sum2 += sum2; sum2 += vv(15); sum2 += sum2; >- FOLD(sum2); >- w += 16; >- } >- mlen += 32; >-#endif >- while ((mlen -= 8) >= 0) { >- sum += ww(0); sum += sum; sum += ww(1); sum += sum; >- sum += ww(2); sum += sum; sum += ww(3); sum += sum; >- FOLD(sum); >- sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2; >- sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2; >- FOLD(sum2); >- w += 4; >- } >- mlen += 8; >- while ((mlen -= 2) >= 0) { >- sum += ww(0); sum += sum; >- sum2 += vv(0); sum2 += sum2; >- w++; >- } >- sum += (sum2 << 8); >-commoncase: >- if (mlen == -1) { >-#if BYTE_ORDER == BIG_ENDIAN >- sum += *(u_char *)w << 8; >-#else >- sum += *(u_char *)w; >-#endif >- } >- FOLD(sum); >- } >- if (mlen == -1) { >- /* We had an odd number of bytes to sum; assume a garbage >- byte of zero and clean up */ >- sum += sum; >- FOLD(sum); >+ u_char b[2]; >+ u_short w; >+ } buf; >+ >+ ipx = mtod(m, struct ipx*); >+ oldtc = ipx->ipx_tc; >+ ipx->ipx_tc = 0; >+ w = &ipx->ipx_len; >+ len -= 2; >+ mlen = 2; >+ >+ for(;;) { >+ mlen = imin(m->m_len - mlen, len); >+ words = mlen / 2; >+ len -= mlen & ~1; >+ while (words >= 16) { >+ SUMADV; SUMADV; SUMADV; SUMADV; >+ SUMADV; SUMADV; SUMADV; SUMADV; >+ SUMADV; SUMADV; SUMADV; SUMADV; >+ SUMADV; SUMADV; SUMADV; SUMADV; >+ words -= 16; >+ } >+ while (words--) >+ SUMADV; >+ if (len == 0) >+ break; >+ mlen &= 1; >+ if (mlen) { >+ buf.b[0] = *(u_char*)w; >+ if (--len == 0) { >+ buf.b[1] = 0; >+ sum += buf.w; >+ break; >+ } >+ } >+ m = m->m_next; >+ if (m == NULL) >+ break; >+ w = mtod(m, u_short*); >+ if (mlen) { >+ buf.b[1] = *(u_char*)w; >+ sum += buf.w; >+ ((u_char*)w)++; >+ if (--len == 0) >+ break; >+ } > } >- /* >- * sum has already been kept to low sixteen bits. >- * just examine result and exit. >- */ >- if(sum == 0xffff) >- sum = 0; >+ >+ ipx->ipx_tc = oldtc; >+ >+ sum = (sum & 0xffff) + (sum >> 16); >+ if (sum >= 0x10000) >+ sum++; >+ if (sum) >+ sum = ~sum; > return (sum); > } >diff -u org/ipx_input.c ./ipx_input.c >--- org/ipx_input.c Mon Jun 22 01:00:00 1998 >+++ ./ipx_input.c Wed Aug 25 16:57:43 1999 >@@ -130,9 +130,7 @@ > register struct mbuf *m; > register struct ipxpcb *ipxp; > struct ipx_ifaddr *ia; >- register int i; > int len, s; >- char oddshortpacket = 0; > > next: > /* >@@ -171,15 +169,6 @@ > > ipx = mtod(m, struct ipx *); > len = ntohs(ipx->ipx_len); >- if ((len < m->m_pkthdr.len) && (oddshortpacket = len & 1)) { >- /* >- * If this packet is of odd length, and the length >- * inside the header is less than the received packet >- * length, preserve garbage byte for possible checksum. >- */ >- len++; >- } >- > /* > * Check that the amount of data in the buffers > * is as at least much as the IPX header would have us expect. >@@ -197,9 +186,8 @@ > } else > m_adj(m, len - m->m_pkthdr.len); > } >- if (ipxcksum && ((i = ipx->ipx_sum) != 0xffff)) { >- ipx->ipx_sum = 0; >- if (i != (ipx->ipx_sum = ipx_cksum(m, len))) { >+ if (ipxcksum && ipx->ipx_sum != 0xffff) { >+ if (ipx->ipx_sum != ipx_cksum(m, len)) { > ipxstat.ipxs_badsum++; > goto bad; > } >@@ -274,9 +262,6 @@ > * Switch out to protocol's input routine. > */ > if (ipxp != NULL) { >- if (oddshortpacket) { >- m_adj(m, -1); >- } > ipxstat.ipxs_delivered++; > if ((ipxp->ipxp_flags & IPXP_ALL_PACKETS) == 0) > switch (ipx->ipx_pt) { >@@ -396,32 +381,15 @@ > goto cleanup; > } > } >- /* XXX >- * I think the checksum generation is bogus. According to the NLSP >- * spec the ipx_tc (hop count) field and the ipx_sum should be >- * zero'ed before generating the checksum, ie. it should not be >- * necesary to recompute it in the forwarding function. >+ /* >+ * We don't need to recompute checksum because ipx_tc field >+ * is ignored by checksum calculation routine, however >+ * it may be desirable to reset checksum if ipxcksum == 0 > */ >- /* need to adjust checksum */ >- if (ipxcksum && ipx->ipx_sum != 0xffff) { >- union bytes { >- u_char c[4]; >- u_short s[2]; >- long l; >- } x; >- register int shift; >- x.l = 0; >- x.c[0] = agedelta; >- shift = (((((int)ntohs(ipx->ipx_len)) + 1) >> 1) - 2) & 0xf; >- x.l = ipx->ipx_sum + (x.s[0] << shift); >- x.l = x.s[0] + x.s[1]; >- x.l = x.s[0] + x.s[1]; >- if (x.l == 0xffff) >- ipx->ipx_sum = 0; >- else >- ipx->ipx_sum = x.l; >- } else >+#if 0 >+ if (!ipxcksum) > ipx->ipx_sum = 0xffff; >+#endif > > error = ipx_outputfl(m, &ipx_droute, flags); > if (error == 0) { >diff -u org/ipx_outputfl.c ./ipx_outputfl.c >--- org/ipx_outputfl.c Sun Apr 11 14:46:00 1999 >+++ ./ipx_outputfl.c Wed Aug 25 12:17:07 1999 >@@ -247,12 +247,8 @@ > ipx->ipx_dna.x_net = dst.sipx_addr.x_net; > m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT); > >- if(ipx->ipx_sum != 0xffff) { >- int len = ntohs(ipx->ipx_len); >- ipx->ipx_sum = 0; >- len = ((len - 1) | 1) + 1; >- ipx->ipx_sum = ipx_cksum(m, len); >- } >+ if(ipx->ipx_sum != 0xffff) >+ ipx->ipx_sum = ipx_cksum(m, ntohs(ipx->ipx_len)); > if(m1) { > error = (*ifp->if_output)(ifp, m1, > (struct sockaddr *)&dst, NULL); >diff -u org/ipx_pcb.c ./ipx_pcb.c >--- org/ipx_pcb.c Sat May 22 00:22:00 1999 >+++ ./ipx_pcb.c Wed Aug 25 12:15:04 1999 >@@ -66,6 +66,8 @@ > return (ENOBUFS); > bzero(ipxp, sizeof *ipxp); > ipxp->ipxp_socket = so; >+ if (ipxcksum) >+ ipxp->ipxp_flags |= IPXP_CHECKSUM; > insque(ipxp, head); > so->so_pcb = (caddr_t)ipxp; > return (0); >diff -u org/ipx_pcb.h ./ipx_pcb.h >--- org/ipx_pcb.h Mon Feb 16 00:00:00 1998 >+++ ./ipx_pcb.h Wed Aug 25 12:15:05 1999 >@@ -64,6 +64,7 @@ > #define IPXP_RAWIN 0x2 /* show headers on input */ > #define IPXP_RAWOUT 0x4 /* show header on output */ > #define IPXP_ALL_PACKETS 0x8 /* Turn off higher proto processing */ >+#define IPXP_CHECKSUM 0x10 /* use checksum on this socket */ > > #define IPX_WILDCARD 1 > >diff -u org/ipx_usrreq.c ./ipx_usrreq.c >--- org/ipx_usrreq.c Sat May 22 00:22:00 1999 >+++ ./ipx_usrreq.c Wed Aug 25 12:17:27 1999 >@@ -214,7 +214,7 @@ > m = mprev; > if ((m->m_flags & M_EXT) == 0 && > (m->m_len + m->m_data < &m->m_dat[MLEN])) { >- m->m_len++; >+ mtod(m, char*)[m->m_len++] = 0; > } else { > struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); > >@@ -250,9 +250,7 @@ > > ipx->ipx_len = htons((u_short)len); > >- if (ipxcksum) { >- ipx->ipx_sum = 0; >- len = ((len - 1) | 1) + 1; >+ if (ipxp->ipxp_flags & IPXP_CHECKSUM) { > ipx->ipx_sum = ipx_cksum(m, len); > } else > ipx->ipx_sum = 0xffff; >@@ -333,6 +331,10 @@ > case SO_HEADERS_ON_INPUT: > mask = IPXP_RAWIN; > goto get_flags; >+ >+ case SO_IPX_CHECKSUM: >+ mask = IPXP_CHECKSUM; >+ goto get_flags; > > case SO_HEADERS_ON_OUTPUT: > mask = IPXP_RAWOUT; >@@ -371,6 +373,9 @@ > case SO_HEADERS_ON_INPUT: > mask = IPXP_RAWIN; > goto set_head; >+ >+ case SO_IPX_CHECKSUM: >+ mask = IPXP_CHECKSUM; > > case SO_HEADERS_ON_OUTPUT: > mask = IPXP_RAWOUT; >Only in .: org >diff -u org/spx_usrreq.c ./spx_usrreq.c >--- org/spx_usrreq.c Sun Feb 7 11:15:00 1999 >+++ ./spx_usrreq.c Wed Aug 25 12:17:54 1999 >@@ -1081,11 +1081,7 @@ > si->si_ack = htons(cb->s_ack); > > if (ipxcksum) { >- si->si_sum = 0; >- len = ntohs(si->si_len); >- if (len & 1) >- len++; >- si->si_sum = ipx_cksum(m, len); >+ si->si_sum = ipx_cksum(m, ntohs(si->si_len)); > } else > si->si_sum = 0xffff;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 13374
: 5653