diff options
author | jhay <jhay@FreeBSD.org> | 1999-08-28 18:21:55 +0000 |
---|---|---|
committer | jhay <jhay@FreeBSD.org> | 1999-08-28 18:21:55 +0000 |
commit | c4958328e037b668484eec86b3cdc4e41ba94e6d (patch) | |
tree | aa08967c601106f45ce5a821832f1130dfae13d2 | |
parent | f98ac3b4e9396a677f79ad70985cb246cb229470 (diff) | |
download | FreeBSD-src-c4958328e037b668484eec86b3cdc4e41ba94e6d.zip FreeBSD-src-c4958328e037b668484eec86b3cdc4e41ba94e6d.tar.gz |
Get rid of the old XNS checksum code and implement it the IPX way.
PR: 13374
Submitted by: Boris Popov <bp@butya.kz>
-rw-r--r-- | sys/netipx/ipx.h | 1 | ||||
-rw-r--r-- | sys/netipx/ipx_cksum.c | 217 | ||||
-rw-r--r-- | sys/netipx/ipx_input.c | 50 | ||||
-rw-r--r-- | sys/netipx/ipx_outputfl.c | 8 | ||||
-rw-r--r-- | sys/netipx/ipx_pcb.c | 2 | ||||
-rw-r--r-- | sys/netipx/ipx_pcb.h | 1 | ||||
-rw-r--r-- | sys/netipx/ipx_usrreq.c | 13 | ||||
-rw-r--r-- | sys/netipx/spx_usrreq.c | 6 |
8 files changed, 85 insertions, 213 deletions
diff --git a/sys/netipx/ipx.h b/sys/netipx/ipx.h index 3bcf5f0..fd23b5c 100644 --- a/sys/netipx/ipx.h +++ b/sys/netipx/ipx.h @@ -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 --git a/sys/netipx/ipx_cksum.c b/sys/netipx/ipx_cksum.c index 4bb9124..02d8f93 100644 --- a/sys/netipx/ipx_cksum.c +++ b/sys/netipx/ipx_cksum.c @@ -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; + u_char b[2]; + u_short w; + } buf; - 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++; + 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; } - sum += (sum2 << 8); -commoncase: - if (mlen == -1) { -#if BYTE_ORDER == BIG_ENDIAN - sum += *(u_char *)w << 8; -#else - sum += *(u_char *)w; -#endif + 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; + } } - FOLD(sum); + 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; + } } - 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); - } - /* - * 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 --git a/sys/netipx/ipx_input.c b/sys/netipx/ipx_input.c index 44634b3..0b51a9b 100644 --- a/sys/netipx/ipx_input.c +++ b/sys/netipx/ipx_input.c @@ -130,9 +130,7 @@ ipxintr() 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 @@ next: 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 @@ next: } 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 @@ ours: * 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 @@ struct mbuf *m; 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 --git a/sys/netipx/ipx_outputfl.c b/sys/netipx/ipx_outputfl.c index fb5c2fb..d5a0266 100644 --- a/sys/netipx/ipx_outputfl.c +++ b/sys/netipx/ipx_outputfl.c @@ -247,12 +247,8 @@ ipx_output_type20(m) 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 --git a/sys/netipx/ipx_pcb.c b/sys/netipx/ipx_pcb.c index 6b57bdc..034751b 100644 --- a/sys/netipx/ipx_pcb.c +++ b/sys/netipx/ipx_pcb.c @@ -66,6 +66,8 @@ ipx_pcballoc(so, head, p) 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 --git a/sys/netipx/ipx_pcb.h b/sys/netipx/ipx_pcb.h index 586f263..366f6c1 100644 --- a/sys/netipx/ipx_pcb.h +++ b/sys/netipx/ipx_pcb.h @@ -64,6 +64,7 @@ struct ipxpcb { #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 --git a/sys/netipx/ipx_usrreq.c b/sys/netipx/ipx_usrreq.c index 2e20f0f..b18b1fb 100644 --- a/sys/netipx/ipx_usrreq.c +++ b/sys/netipx/ipx_usrreq.c @@ -214,7 +214,7 @@ ipx_output(ipxp, m0) 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_output(ipxp, m0) 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 @@ ipx_ctloutput(so, sopt) 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; @@ -372,6 +374,9 @@ ipx_ctloutput(so, sopt) mask = IPXP_RAWIN; goto set_head; + case SO_IPX_CHECKSUM: + mask = IPXP_CHECKSUM; + case SO_HEADERS_ON_OUTPUT: mask = IPXP_RAWOUT; set_head: diff --git a/sys/netipx/spx_usrreq.c b/sys/netipx/spx_usrreq.c index 7418eac..be8eb97 100644 --- a/sys/netipx/spx_usrreq.c +++ b/sys/netipx/spx_usrreq.c @@ -1081,11 +1081,7 @@ send: 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; |