From d4f62dcb69c639b3aad368050143bc300bb7a1e6 Mon Sep 17 00:00:00 2001 From: cgd Date: Wed, 7 Jun 1995 00:13:52 +0000 Subject: [PATCH] update from Ignatios Souvatzis --- sys/arch/amiga/dev/if_bah.c | 35 ++- sys/arch/amiga/dev/if_bahreg.h | 22 +- sys/dev/ic/smc90cx6.c | 35 ++- sys/dev/ic/smc90cx6reg.h | 22 +- sys/net/if_arc.h | 85 +++++-- sys/net/if_arcsubr.c | 406 +++++++++++++++++++++++++++++---- sys/netinet/if_arc.h | 85 +++++-- 7 files changed, 542 insertions(+), 148 deletions(-) diff --git a/sys/arch/amiga/dev/if_bah.c b/sys/arch/amiga/dev/if_bah.c index 5f85e96409b4..287676356353 100644 --- a/sys/arch/amiga/dev/if_bah.c +++ b/sys/arch/amiga/dev/if_bah.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_bah.c,v 1.7 1995/04/15 10:35:24 cgd Exp $ */ +/* $NetBSD: if_bah.c,v 1.8 1995/06/07 00:16:54 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Ignatios Souvatzis @@ -172,7 +172,7 @@ struct bah_softc { int bahmatch __P((struct device *, void *, void *)); void bahattach __P((struct device *, struct device *, void *)); -void bah_ini __P((struct bah_softc *)); +void bah_init __P((struct bah_softc *)); void bah_reset __P((struct bah_softc *)); void bah_stop __P((struct bah_softc *)); void bah_start __P((struct ifnet *)); @@ -766,7 +766,7 @@ bah_srint(sc, dummy) struct bah_softc *sc; void *dummy; { - int buffer, buffer1, len, len1, amount, offset, s, i; + int buffer, buffer1, len, len1, amount, offset, s, i, type; u_char __volatile *bah_ram_ptr; struct mbuf *m, *dst, *head; struct arc_header *ah; @@ -816,25 +816,15 @@ bah_srint(sc, dummy) } m->m_pkthdr.rcvif = ifp; - m->m_len = 0; /* * Align so that IP packet will be longword aligned. Here we * assume that m_data of new packet is longword aligned. - * When implementing RFC1201, we might have to change it to 2, - * (2*sizeof(ulong) - ARC_HDRLEN - sizeof(splitflag) - sizeof(pckid)) - * possibly packet type dependent. + * When implementing PHDS, we might have to change it to 2, + * (2*sizeof(ulong) - ARC_HDRNEWLEN)), packet type dependent. */ - m->m_data += 1; /* sizeof(u_long) - ARC_HDRLEN */ - - head = m; - - ah = mtod(head, struct arc_header *); bah_ram_ptr = sc->sc_base->buffers + buffer*512*2; - - ah->arc_shost = bah_ram_ptr[0*2]; - ah->arc_dhost = bah_ram_ptr[1*2]; offset = bah_ram_ptr[2*2]; if (offset) len = 256 - offset; @@ -842,9 +832,18 @@ bah_srint(sc, dummy) offset = bah_ram_ptr[3*2]; len = 512 - offset; } - m->m_pkthdr.len = len+2; /* whole packet length */ - m->m_len += 2; /* mbuf filled with ARCnet addresses */ - bah_ram_ptr += offset*2; /* ram buffer continues there */ + type = bah_ram_ptr[offset*2]; + m->m_data += 1 + arc_isphds(type); + + head = m; + ah = mtod(head, struct arc_header *); + + ah->arc_shost = bah_ram_ptr[0*2]; + ah->arc_dhost = bah_ram_ptr[1*2]; + + m->m_pkthdr.len = len+2; /* whole packet length */ + m->m_len = 2; /* mbuf filled with ARCnet addresses */ + bah_ram_ptr += offset*2; /* ram buffer continues there */ while (len > 0) { diff --git a/sys/arch/amiga/dev/if_bahreg.h b/sys/arch/amiga/dev/if_bahreg.h index 9cb874a312f5..568d8c44d4fd 100644 --- a/sys/arch/amiga/dev/if_bahreg.h +++ b/sys/arch/amiga/dev/if_bahreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_bahreg.h,v 1.3 1995/03/02 09:12:45 chopps Exp $ */ +/* $NetBSD: if_bahreg.h,v 1.4 1995/06/07 00:16:59 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Ignatios Souvatzis @@ -48,16 +48,16 @@ #define PRODUCT_2 9 struct a2060 { - volatile u_char kick1; - u_char pad1[16383]; - volatile u_char status; /* also intmask */ - u_char pad2; - volatile u_char command; - u_char pad3[16381]; - volatile u_char buffers[4096]; /* even bytes only */ - u_char pad4[12228]; - volatile u_char kick2; - u_char pad5[16383]; + volatile u_int8_t kick1; + u_int8_t pad1[16383]; + volatile u_int8_t status; /* also intmask */ + u_int8_t pad2; + volatile u_int8_t command; + u_int8_t pad3[16381]; + volatile u_int8_t buffers[4096]; /* even bytes only */ + u_int8_t pad4[12228]; + volatile u_int8_t kick2; + u_int8_t pad5[16383]; }; #define checkbyte buffers[0] diff --git a/sys/dev/ic/smc90cx6.c b/sys/dev/ic/smc90cx6.c index e0fe9e41173c..35cce3f37b33 100644 --- a/sys/dev/ic/smc90cx6.c +++ b/sys/dev/ic/smc90cx6.c @@ -1,4 +1,4 @@ -/* $NetBSD: smc90cx6.c,v 1.7 1995/04/15 10:35:24 cgd Exp $ */ +/* $NetBSD: smc90cx6.c,v 1.8 1995/06/07 00:16:54 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Ignatios Souvatzis @@ -172,7 +172,7 @@ struct bah_softc { int bahmatch __P((struct device *, void *, void *)); void bahattach __P((struct device *, struct device *, void *)); -void bah_ini __P((struct bah_softc *)); +void bah_init __P((struct bah_softc *)); void bah_reset __P((struct bah_softc *)); void bah_stop __P((struct bah_softc *)); void bah_start __P((struct ifnet *)); @@ -766,7 +766,7 @@ bah_srint(sc, dummy) struct bah_softc *sc; void *dummy; { - int buffer, buffer1, len, len1, amount, offset, s, i; + int buffer, buffer1, len, len1, amount, offset, s, i, type; u_char __volatile *bah_ram_ptr; struct mbuf *m, *dst, *head; struct arc_header *ah; @@ -816,25 +816,15 @@ bah_srint(sc, dummy) } m->m_pkthdr.rcvif = ifp; - m->m_len = 0; /* * Align so that IP packet will be longword aligned. Here we * assume that m_data of new packet is longword aligned. - * When implementing RFC1201, we might have to change it to 2, - * (2*sizeof(ulong) - ARC_HDRLEN - sizeof(splitflag) - sizeof(pckid)) - * possibly packet type dependent. + * When implementing PHDS, we might have to change it to 2, + * (2*sizeof(ulong) - ARC_HDRNEWLEN)), packet type dependent. */ - m->m_data += 1; /* sizeof(u_long) - ARC_HDRLEN */ - - head = m; - - ah = mtod(head, struct arc_header *); bah_ram_ptr = sc->sc_base->buffers + buffer*512*2; - - ah->arc_shost = bah_ram_ptr[0*2]; - ah->arc_dhost = bah_ram_ptr[1*2]; offset = bah_ram_ptr[2*2]; if (offset) len = 256 - offset; @@ -842,9 +832,18 @@ bah_srint(sc, dummy) offset = bah_ram_ptr[3*2]; len = 512 - offset; } - m->m_pkthdr.len = len+2; /* whole packet length */ - m->m_len += 2; /* mbuf filled with ARCnet addresses */ - bah_ram_ptr += offset*2; /* ram buffer continues there */ + type = bah_ram_ptr[offset*2]; + m->m_data += 1 + arc_isphds(type); + + head = m; + ah = mtod(head, struct arc_header *); + + ah->arc_shost = bah_ram_ptr[0*2]; + ah->arc_dhost = bah_ram_ptr[1*2]; + + m->m_pkthdr.len = len+2; /* whole packet length */ + m->m_len = 2; /* mbuf filled with ARCnet addresses */ + bah_ram_ptr += offset*2; /* ram buffer continues there */ while (len > 0) { diff --git a/sys/dev/ic/smc90cx6reg.h b/sys/dev/ic/smc90cx6reg.h index bedb9ee4a4e9..f2ec2a06e5cf 100644 --- a/sys/dev/ic/smc90cx6reg.h +++ b/sys/dev/ic/smc90cx6reg.h @@ -1,4 +1,4 @@ -/* $NetBSD: smc90cx6reg.h,v 1.3 1995/03/02 09:12:45 chopps Exp $ */ +/* $NetBSD: smc90cx6reg.h,v 1.4 1995/06/07 00:16:59 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Ignatios Souvatzis @@ -48,16 +48,16 @@ #define PRODUCT_2 9 struct a2060 { - volatile u_char kick1; - u_char pad1[16383]; - volatile u_char status; /* also intmask */ - u_char pad2; - volatile u_char command; - u_char pad3[16381]; - volatile u_char buffers[4096]; /* even bytes only */ - u_char pad4[12228]; - volatile u_char kick2; - u_char pad5[16383]; + volatile u_int8_t kick1; + u_int8_t pad1[16383]; + volatile u_int8_t status; /* also intmask */ + u_int8_t pad2; + volatile u_int8_t command; + u_int8_t pad3[16381]; + volatile u_int8_t buffers[4096]; /* even bytes only */ + u_int8_t pad4[12228]; + volatile u_int8_t kick2; + u_int8_t pad5[16383]; }; #define checkbyte buffers[0] diff --git a/sys/net/if_arc.h b/sys/net/if_arc.h index ae674d51b27c..53fdaa8fd20e 100644 --- a/sys/net/if_arc.h +++ b/sys/net/if_arc.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_arc.h,v 1.4 1995/04/14 17:09:39 chopps Exp $ */ +/* $NetBSD: if_arc.h,v 1.5 1995/06/07 00:14:04 cgd Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -41,7 +41,7 @@ * don't know who uses this. */ struct arc_addr { - u_char arc_addr_octet[1]; + u_int8_t arc_addr_octet[1]; }; /* @@ -49,38 +49,75 @@ struct arc_addr { * as given to interface code. */ struct arc_header { - u_char arc_shost; - u_char arc_dhost; - u_char arc_type; + u_int8_t arc_shost; + u_int8_t arc_dhost; + u_int8_t arc_type; + /* + * only present for newstyle encoding with LL fragmentation. + * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead. + */ + u_int8_t arc_flag; + u_int16_t arc_seqid; + + /* + * only present in exception packets (arc_flag == 0xff) + */ + u_int8_t arc_type2; /* same as arc_type */ + u_int8_t arc_flag2; /* real flag value */ + u_int16_t arc_seqid2; /* real seqid value */ }; -#define ARC_HDRLEN 3 +#define ARC_ADDR_LEN 1 + +#define ARC_HDRLEN 3 +#define ARC_HDRNEWLEN 6 + +/* these lengths are data link layer length - 2*ARC_ADDR_LEN */ +#define ARC_MIN_LEN 1 +#define ARC_MIN_FORBID_LEN 254 +#define ARC_MAX_FORBID_LEN 256 +#define ARC_MAX_LEN 508 + /* RFC 1051 */ -#define ARCTYPE_IP_OLD 240 /* IP protocol */ -#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ +#define ARCTYPE_IP_OLD 240 /* IP protocol */ +#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ /* RFC 1201 */ -#define ARCTYPE_IP 212 /* IP protocol */ -#define ARCTYPE_ARP 213 /* address resolution protocol */ -#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ +#define ARCTYPE_IP 212 /* IP protocol */ +#define ARCTYPE_ARP 213 /* address resolution protocol */ +#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ -#define ARCMTU 507 -#define ARCMIN 0 +#define ARCTYPE_ATALK 221 /* Appletalk */ +#define ARCTYPE_BANIAN 247 /* Banyan Vines */ +#define ARCTYPE_IPX 250 /* Novell IPX */ + +#define ARCMTU 507 +#define ARCMIN 0 struct arccom { - struct ifnet ac_if; /* network-visible interface */ - u_char ac_anaddr; /* arcnet hardware address */ - /* only first byte used for arc */ - struct in_addr ac_ipaddr; /* copy of ip address- XXX */ + struct ifnet ac_if; /* network-visible interface */ + u_int8_t ac_anaddr; /* arcnet hardware address */ + struct in_addr ac_ipaddr; /* copy of ip address- XXX */ + + u_int16_t ac_seqid; /* seq. id used by PHDS encap. */ + + struct ac_frag { + u_int8_t af_maxflag; /* from first packet */ + u_int8_t af_lastseen; /* last split flag seen */ + u_int16_t af_seqid; + struct mbuf *af_packet; + } ac_fragtab[256]; /* indexed by sender ll address */ + }; -#ifdef _KERNEL -u_char arcbroadcastaddr; +#ifdef _KERNEL +u_int8_t arcbroadcastaddr; -void arc_ifattach __P((struct ifnet *)); -char *arc_sprintf __P((u_char *)); -void arc_input __P((struct ifnet *, struct mbuf *)); -int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, - struct rtentry *)); +void arc_ifattach __P((struct ifnet *)); +char *arc_sprintf __P((u_int8_t *)); +void arc_input __P((struct ifnet *, struct mbuf *)); +int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *)); +int arc_isphds __P((int)); #endif diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c index ee9133cc5af6..7cc8feda20bb 100644 --- a/sys/net/if_arcsubr.c +++ b/sys/net/if_arcsubr.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_arcsubr.c,v 1.3 1995/04/14 17:06:39 chopps Exp $ */ +/* $NetBSD: if_arcsubr.c,v 1.4 1995/06/07 00:13:52 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Ignatios Souvatzis @@ -61,10 +61,27 @@ #endif #include -u_char arcbroadcastaddr = 0; +#ifndef ARC_PHDSMTU +#define ARC_PHDSMTU 1500 +#endif + +/* why isnt this in /sys/sys/mbuf.h?? */ +extern struct mbuf *m_split __P((struct mbuf *, int, int)); +static struct mbuf *arc_defrag __P((struct ifnet *, struct mbuf *)); + +/* + * RC1201 requires us to have this configurable. We have it only per + * machine at the moment... there is no generic "set mtu" ioctl, AFAICS. + * Anyway, it is possible to binpatch this or set it per kernel config + * option. + */ +#if ARC_PHDSMTU > 60480 +ERROR: The arc_phdsmtu is ARC_PHDSMTU, but must not exceed 60480. +#endif +u_int16_t arc_phdsmtu = ARC_PHDSMTU; +u_int8_t arcbroadcastaddr = 0; #define senderr(e) { error = (e); goto bad;} - #define SIN(s) ((struct sockaddr_in *)s) /* @@ -79,17 +96,24 @@ arc_output(ifp, m0, dst, rt0) struct sockaddr *dst; struct rtentry *rt0; { - int s, error = 0; - u_char atype, adst; - register struct mbuf *m = m0; - register struct rtentry *rt; - struct mbuf *mcopy = (struct mbuf *)0; + struct mbuf *m, *m1, *mcopy; + struct rtentry *rt; + struct arccom *ac; register struct arc_header *ah; - int off, len = m->m_pkthdr.len; - struct arccom *ac = (struct arccom *)ifp; + int off, len; + int s, error, newencoding; + u_int8_t atype, adst; + int tfrags, sflag, fsflag, rsflag; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) senderr(ENETDOWN); + + error = newencoding = 0; + ac = (struct arccom *)ifp; + m = m0; + len = m->m_pkthdr.len; + mcopy = m1 = NULL; + ifp->if_lastchange = time; if (rt = rt0) { if ((rt->rt_flags & RTF_UP) == 0) { @@ -113,8 +137,8 @@ arc_output(ifp, m0, dst, rt0) time.tv_sec < rt->rt_rmx.rmx_expire) senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); } - switch (dst->sa_family) { + switch (dst->sa_family) { #ifdef INET case AF_INET: @@ -130,9 +154,16 @@ arc_output(ifp, m0, dst, rt0) if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) mcopy = m_copy(m, 0, (int)M_COPYALL); off = m->m_pkthdr.len - m->m_len; - atype = ARCTYPE_IP_OLD; + if (ifp->if_flags & IFF_LINK0) { + atype = ARCTYPE_IP; + newencoding = 1; + } else { + atype = ARCTYPE_IP_OLD; + newencoding = 0; + } break; #endif + case AF_UNSPEC: ah = (struct arc_header *)dst->sa_data; adst = ah->arc_dhost; @@ -145,9 +176,9 @@ arc_output(ifp, m0, dst, rt0) senderr(EAFNOSUPPORT); } - if (mcopy) (void) looutput(ifp, mcopy, dst, rt); + /* * Add local net header. If no space in first mbuf, * allocate another. @@ -157,37 +188,308 @@ arc_output(ifp, m0, dst, rt0) * the wire. At this point, it contains source, destination and * packet type. */ - M_PREPEND(m, ARC_HDRLEN, M_DONTWAIT); - if (m == 0) - senderr(ENOBUFS); - ah = mtod(m, struct arc_header *); - ah->arc_type = atype; - ah->arc_dhost= adst; - ah->arc_shost= ac->ac_anaddr; - s = splimp(); - /* - * Queue message on interface, and start output if interface - * not yet active. - */ - if (IF_QFULL(&ifp->if_snd)) { - IF_DROP(&ifp->if_snd); - splx(s); - senderr(ENOBUFS); - } - IF_ENQUEUE(&ifp->if_snd, m); - if ((ifp->if_flags & IFF_OACTIVE) == 0) - (*ifp->if_start)(ifp); - splx(s); + if (newencoding) { + ++ac->ac_seqid; /* make the seqid unique */ + + tfrags = (len + 503) / 504; + fsflag = 2*tfrags-3; + sflag = 0; + rsflag = fsflag; + + while (sflag < fsflag) { + /* we CAN'T have short packets here */ + m1 = m_split(m, 504, M_DONTWAIT); + if (m1 == 0) + senderr(ENOBUFS); + + M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT); + if (m == 0) + senderr(ENOBUFS); + m = m_pullup(m,ARC_HDRNEWLEN); + if (m == 0) + senderr(ENOBUFS); + + ah = mtod(m, struct arc_header *); + ah->arc_type = atype; + ah->arc_dhost = adst; + ah->arc_shost = ac->ac_anaddr; + ah->arc_flag = rsflag; + ah->arc_seqid = ac->ac_seqid; + + s = splimp(); + /* + * Queue message on interface, and start output if + * interface not yet active. + */ + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); + splx(s); + senderr(ENOBUFS); + } + IF_ENQUEUE(&ifp->if_snd, m); + if ((ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + splx(s); - ifp->if_obytes += len + ARC_HDRLEN; + /* we don't count the hardwares lenght bytes here */ + ifp->if_obytes += 504 + ARC_HDRNEWLEN; + + m = m1; + len -= 504; + sflag += 2; + rsflag = sflag; + } + m1 = NULL; + + M_PREPEND(m, ARC_HDRNEWLEN, M_DONTWAIT); + if (m == 0) + senderr(ENOBUFS); + m = m_pullup(m, ARC_HDRNEWLEN); + if (m == 0) + senderr(ENOBUFS); + + ah = mtod(m, struct arc_header *); + ah->arc_type = atype; + ah->arc_flag = sflag; + ah->arc_seqid= ac->ac_seqid; + + /* here we can have small, especially forbidden packets */ + + if ((len >= ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) && + (len <= ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) { + + M_PREPEND(m, 4, M_DONTWAIT); + if (m == 0) + senderr(ENOBUFS); + + m = m_pullup(m, ARC_HDRNEWLEN); + if (m == 0) + senderr(ENOBUFS); + + ah = mtod(m, struct arc_header *); + ah->arc_type = atype; + ah->arc_flag = 0xFF; + ah->arc_seqid= 0xFFFF; + len += 4; + } + + ah->arc_dhost= adst; + ah->arc_shost= ac->ac_anaddr; + + s = splimp(); + /* + * Queue message on interface, and start output if interface + * not yet active. + */ + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); + splx(s); + senderr(ENOBUFS); + } + IF_ENQUEUE(&ifp->if_snd, m); + if ((ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + splx(s); + + ifp->if_obytes += len + ARC_HDRNEWLEN; + + } else { + M_PREPEND(m, ARC_HDRLEN, M_DONTWAIT); + if (m == 0) + senderr(ENOBUFS); + ah = mtod(m, struct arc_header *); + ah->arc_type = atype; + ah->arc_dhost= adst; + ah->arc_shost= ac->ac_anaddr; + s = splimp(); + /* + * Queue message on interface, and start output if interface + * not yet active. + */ + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); + splx(s); + senderr(ENOBUFS); + } + IF_ENQUEUE(&ifp->if_snd, m); + if ((ifp->if_flags & IFF_OACTIVE) == 0) + (*ifp->if_start)(ifp); + splx(s); + + ifp->if_obytes += len + ARC_HDRLEN; + } return (error); bad: + if (m1) + m_freem(m1); if (m) m_freem(m); return (error); } +/* + * Defragmenter. Returns mbuf if last packet found, else + * NULL. frees imcoming mbuf as necessary. + */ + +__inline struct mbuf * +arc_defrag(ifp, m) + struct ifnet *ifp; + struct mbuf *m; +{ + struct arc_header *ah, *ah1; + struct arccom *ac; + struct ac_frag *af; + struct mbuf *m1; + char *s; + int newflen; + u_char src,dst,typ; + + ac = (struct arccom *)ifp; + + m = m_pullup(m, ARC_HDRNEWLEN); + if (m == NULL) { + ++ifp->if_ierrors; + return NULL; + } + + ah = mtod(m, struct arc_header *); + typ = ah->arc_type; + + if (!arc_isphds(typ)) + return m; + + src = ah->arc_shost; + dst = ah->arc_dhost; + + if (ah->arc_flag == 0xff) { + m_adj(m, 4); + + m = m_pullup(m, ARC_HDRNEWLEN); + if (m == NULL) { + ++ifp->if_ierrors; + return NULL; + } + + ah = mtod(m, struct arc_header *); + ah->arc_shost = src; + ah->arc_dhost = dst; + ah->arc_type = typ; + } + + af = &ac->ac_fragtab[src]; + m1 = af->af_packet; + s = "debug code error"; + + if (ah->arc_flag & 1) { + /* + * first fragment. We always initialize, which is + * about the right thing to do, as we only want to + * accept one fragmented packet per src at a time. + */ + if (m1 != NULL) + m_freem(m1); + + af->af_packet = m; + m1 = m; + af->af_maxflag = ah->arc_flag; + af->af_lastseen = 0; + af->af_seqid = ah->arc_seqid; + + return NULL; + /* notreached */ + } else { + /* check for unfragmented packet */ + if (ah->arc_flag == 0) + return m; + + /* do we have a first packet from that src? */ + if (m1 == NULL) { + s = "no first frag"; + goto outofseq; + } + + ah1 = mtod(m1, struct arc_header *); + + if (ah->arc_seqid != ah1->arc_seqid) { + s = "seqid differs"; + goto outofseq; + } + + if (ah->arc_type != ah1->arc_type) { + s = "type differs"; + goto outofseq; + } + + if (ah->arc_dhost != ah1->arc_dhost) { + s = "dest host differs"; + goto outofseq; + } + + /* typ, seqid and dst are ok here. */ + + if (ah->arc_flag == af->af_lastseen) { + m_freem(m); + return NULL; + } + + if (ah->arc_flag == af->af_lastseen + 2) { + /* ok, this is next fragment */ + af->af_lastseen = ah->arc_flag; + m_adj(m,ARC_HDRNEWLEN); + + /* + * m_cat might free the first mbuf (with pkthdr) + * in 2nd chain; therefore: + */ + + newflen = m->m_pkthdr.len; + + m_cat(m1,m); + + m1->m_pkthdr.len += newflen; + + /* is it the last one? */ + if (af->af_lastseen > af->af_maxflag) { + af->af_packet = NULL; + return(m1); + } else + return NULL; + } + s = "other reason"; + /* if all else fails, it is out of sequence, too */ + } +outofseq: + if (m1) { + m_freem(m1); + af->af_packet = NULL; + } + + if (m) + m_freem(m); + + log(LOG_INFO,"%s%d: got out of seq. packet: %s\n", + ifp->if_name, ifp->if_unit, s); + + return NULL; +} + +/* + * return 1 if Packet Header Definition Standard, else 0. + * For now: old IP, old ARP aren't obviously. Lacking correct information, + * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. + * (Apple and Novell corporations were involved, among others, in PHDS work). + * Easiest is to assume that everybody else uses that, too. + */ +int +arc_isphds(type) + int type; +{ + return ((type != ARCTYPE_IP_OLD && + type != ARCTYPE_ARP_OLD)); +} + /* * Process a received Arcnet packet; * the packet is in the mbuf chain m with @@ -200,14 +502,20 @@ arc_input(ifp, m) { register struct arc_header *ah; register struct ifqueue *inq; - u_char atype; + u_int8_t atype; int s; if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); return; } - ah = mtod(m,struct arc_header *); + + /* possibly defragment: */ + m = arc_defrag(ifp, m); + if (m == NULL) + return; + + ah = mtod(m, struct arc_header *); ifp->if_lastchange = time; ifp->if_ibytes += m->m_pkthdr.len; @@ -220,6 +528,12 @@ arc_input(ifp, m) atype = ah->arc_type; switch (atype) { #ifdef INET + case ARCTYPE_IP: + m_adj(m,ARC_HDRNEWLEN); + schednetisr(NETISR_IP); + inq = &ipintrq; + break; + case ARCTYPE_IP_OLD: m_adj(m,ARC_HDRLEN); schednetisr(NETISR_IP); @@ -246,7 +560,7 @@ arc_input(ifp, m) static char digits[] = "0123456789abcdef"; char * arc_sprintf(ap) - register u_char *ap; + register u_int8_t *ap; { static char arcbuf[3]; register char *cp = arcbuf; @@ -266,14 +580,22 @@ arc_ifattach(ifp) { register struct ifaddr *ifa; register struct sockaddr_dl *sdl; + register struct arccom *ac; ifp->if_type = IFT_ARCNET; ifp->if_addrlen = 1; ifp->if_hdrlen = ARC_HDRLEN; - ifp->if_mtu = ARCMTU; - if (((struct arccom *)ifp)->ac_anaddr == 0) { - log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts.\n\ -Please change it and ifconfig %s%d down up\n", + if (ifp->if_flags & IFF_LINK0 && arc_phdsmtu > 60480) + log(LOG_ERR, + "%s%d: arc_phdsmtu is %d, but must not exceed 60480", + ifp->if_name, ifp->if_unit, arc_phdsmtu); + + ifp->if_mtu = (ifp->if_flags & IFF_LINK0 ? arc_phdsmtu : ARCMTU); + ac = (struct arccom *)ifp; + ac->ac_seqid = (time.tv_sec) & 0xFFFF; /* try to make seqid unique */ + if (ac->ac_anaddr == 0) { + /* XXX this message isn't entirely clear, to me -- cgd */ + log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts. Please change it and ifconfig %s%d down up\n", ifp->if_name,ifp->if_unit,ifp->if_name,ifp->if_unit); } for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) diff --git a/sys/netinet/if_arc.h b/sys/netinet/if_arc.h index ae674d51b27c..53fdaa8fd20e 100644 --- a/sys/netinet/if_arc.h +++ b/sys/netinet/if_arc.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_arc.h,v 1.4 1995/04/14 17:09:39 chopps Exp $ */ +/* $NetBSD: if_arc.h,v 1.5 1995/06/07 00:14:04 cgd Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -41,7 +41,7 @@ * don't know who uses this. */ struct arc_addr { - u_char arc_addr_octet[1]; + u_int8_t arc_addr_octet[1]; }; /* @@ -49,38 +49,75 @@ struct arc_addr { * as given to interface code. */ struct arc_header { - u_char arc_shost; - u_char arc_dhost; - u_char arc_type; + u_int8_t arc_shost; + u_int8_t arc_dhost; + u_int8_t arc_type; + /* + * only present for newstyle encoding with LL fragmentation. + * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead. + */ + u_int8_t arc_flag; + u_int16_t arc_seqid; + + /* + * only present in exception packets (arc_flag == 0xff) + */ + u_int8_t arc_type2; /* same as arc_type */ + u_int8_t arc_flag2; /* real flag value */ + u_int16_t arc_seqid2; /* real seqid value */ }; -#define ARC_HDRLEN 3 +#define ARC_ADDR_LEN 1 + +#define ARC_HDRLEN 3 +#define ARC_HDRNEWLEN 6 + +/* these lengths are data link layer length - 2*ARC_ADDR_LEN */ +#define ARC_MIN_LEN 1 +#define ARC_MIN_FORBID_LEN 254 +#define ARC_MAX_FORBID_LEN 256 +#define ARC_MAX_LEN 508 + /* RFC 1051 */ -#define ARCTYPE_IP_OLD 240 /* IP protocol */ -#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ +#define ARCTYPE_IP_OLD 240 /* IP protocol */ +#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ /* RFC 1201 */ -#define ARCTYPE_IP 212 /* IP protocol */ -#define ARCTYPE_ARP 213 /* address resolution protocol */ -#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ +#define ARCTYPE_IP 212 /* IP protocol */ +#define ARCTYPE_ARP 213 /* address resolution protocol */ +#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ -#define ARCMTU 507 -#define ARCMIN 0 +#define ARCTYPE_ATALK 221 /* Appletalk */ +#define ARCTYPE_BANIAN 247 /* Banyan Vines */ +#define ARCTYPE_IPX 250 /* Novell IPX */ + +#define ARCMTU 507 +#define ARCMIN 0 struct arccom { - struct ifnet ac_if; /* network-visible interface */ - u_char ac_anaddr; /* arcnet hardware address */ - /* only first byte used for arc */ - struct in_addr ac_ipaddr; /* copy of ip address- XXX */ + struct ifnet ac_if; /* network-visible interface */ + u_int8_t ac_anaddr; /* arcnet hardware address */ + struct in_addr ac_ipaddr; /* copy of ip address- XXX */ + + u_int16_t ac_seqid; /* seq. id used by PHDS encap. */ + + struct ac_frag { + u_int8_t af_maxflag; /* from first packet */ + u_int8_t af_lastseen; /* last split flag seen */ + u_int16_t af_seqid; + struct mbuf *af_packet; + } ac_fragtab[256]; /* indexed by sender ll address */ + }; -#ifdef _KERNEL -u_char arcbroadcastaddr; +#ifdef _KERNEL +u_int8_t arcbroadcastaddr; -void arc_ifattach __P((struct ifnet *)); -char *arc_sprintf __P((u_char *)); -void arc_input __P((struct ifnet *, struct mbuf *)); -int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, - struct rtentry *)); +void arc_ifattach __P((struct ifnet *)); +char *arc_sprintf __P((u_int8_t *)); +void arc_input __P((struct ifnet *, struct mbuf *)); +int arc_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *)); +int arc_isphds __P((int)); #endif