diff -ur --new-file old/atm/BUGS new/atm/BUGS --- old/atm/BUGS Tue Apr 22 23:35:06 1997 +++ new/atm/BUGS Tue Aug 4 20:41:05 1998 @@ -1,140 +1,8 @@ -Known bugs and restrictions in version 0.31 +Known bugs and restrictions in version 0.39 =========================================== - - like in 0.30 - -Known bugs and restrictions in version 0.30 -=========================================== - - - Arequipa sometimes eats the first packet (probably fixed) - - ENI driver should be more tolerant about data alignment when sending - - libresolve conflicts with libc on some systems - - atmarp is said to break proxy ARP - - -Known bugs and restrictions in version 0.29 -=========================================== - - - Arequipa sometimes eats the first packet - - atmsigd -N is reported to fail in some unspecified way - - ENI driver should be more tolerant about data alignment when sending - - libresolve conflicts with libc on some systems - - qgen is said to exhibit memory leak on q_open/q_close (need to verify) - - atmarp is said to break proxy ARP - - atmsigd reported to die and hang in eni.c:close_tx (fixed ?) - - atmarpd sometimes complains about "ARP: unknown hw protocol 0xaaaa". (fixed?) - - -Known bugs and restrictions in version 0.28 -=========================================== - - - ENI driver seems to get confused when closing VC with low PCR and data - pending (this is a more precise diagnosis of the "ident mismatch" problem) - - didn't fix all the 0.27 and 0.28 problems listed below - - select is reported to fail miserably when used with atmtcp - - -Known bugs and restrictions in version 0.27 -=========================================== - - - Arequipa sometimes eats the first packet - - atmsigd reported to die and hang in eni.c:close_tx - - ENI driver still emits "ident mismatch" - - atmsigd -N is reported to fail in some unspecified way - - didn't fix all the 0.27 problems listed below - - atmarpd sometimes complains about "ARP: unknown hw protocol 0xaaaa". Might - indicate that data gets corrupted somewhere. - - -Known bugs and restrictions in version 0.26 -=========================================== - - - the AAL changes probably broke LANE - - ENI driver should be more tolerant about data alignment when sending - libresolve conflicts with libc on some systems - - atmarpd sometimes loses the VC to the ATMARP server - - qgen is said to exhibit memory leak on q_open/q_close (need to verify) - - atmarp is said to break proxy ARP - - -Known bugs and restrictions in version 0.19 -=========================================== - -IP over ATM ------------ - - - first ping freezes some systems (???) - - kernel crashes badly if (remote) ARP server is set to local machine - - clients don't always refresh their entry at ARP server (fixed ?) - - IP interfaces must not be reconfigured while up - - requires local ATM address to be set on interface 0 on startup (fixed ?) - - encapsulation is broken (but works good enough for now) - - atmarpd may not recover properly from link failures (but a resolution - request or such usually cures that) (fixed ?) - - atmarpd shouldn't invalidate entries on the first timeout in valid state - but rather try one revalidation request first - - Arequipa leaves stale SVCs if atmsigd has disappeared - - creation of the hard_header isn't "clean" - -Signaling ---------- - - - never initiates a RESTART procedure - - doesn't implement T322 (i.e. STATUS ENQUIRY is not retried) - - atmsigd sometimes terminates ungracefully when encountering errors in - signaling messages - - no support for repeated information elements - - there's currently no way to obtain SVC traffic parameters indicated by - the remote party - - SSCOP doesn't update the window properly - -ENI-155p driver ---------------- - - - TX freezes on some systems when starting atmsigd and ilmid (???) - - driver may hang under heavy load with LANE - - shouldn't depend on sizeof(unsigned long) == 4 - - sometimes doesn't unqueue RX PDUs when being tortured with aping - (or, more generally, seems to mis-calculate buffer usage after CR errors, - so that close hangs) - - SUNI loopback is untested - - support for multiple adapters per machine is untested - - doesn't handle unsolicited OAM cells gracefully - - adapter may deadlock if buffer full of loss indications - - doesn't properly zero pad area of AAL5 PDUs - - driver should use bottom-half interrupt handler - -ZN1221 driver -------------- - - - shouldn't depend on sizeof(unsigned long) == 4 - - still hangs from time to time when sending - - support for multiple adapters per machine is untested - - SONET/SDH framing support is untested - - doesn't support single-copy in this release - -ATM over TCP ------------- - - - is reported to hang under load - - signaling is reported not to work over ATMTCP - - driver is very limited in functionality - - system may crash if atmtcp is killed - - can't run IP over ATM using ATM over TCP - - ATMTCP interfaces can't be taken down - -ATM sockets and "common" layer ------------------------------- - - - single copy currently uses massive amounts of brute force to flush TLBs ... - - SVC close may block forever (waiting for atmsigd) - - polled devices are broken as designed (and may eventually go away ...) - - some system calls don't return full SVC SAP information - - poor integration with other network code - -Miscellaneous -------------- - - - there are lots of known bugs not listed in this file (look for @@@ in - the source) - - there are *still* no "nice" applications + - ENI driver loses synchronization on some systems, leading to panics or hung + VCs (these may be two distinct problems) + - few if any drivers build properly as modules + - LANE and signaling may conspire to crash the system diff -ur --new-file old/atm/CHANGES new/atm/CHANGES --- old/atm/CHANGES Thu Jun 25 14:14:07 1998 +++ new/atm/CHANGES Tue Aug 4 20:48:14 1998 @@ -1,3 +1,60 @@ +Version 0.38 to 0.39 (4-AUG-1998) +==================== + +Bug fixes +--------- + + - added missing #include in tcpsw.c (fixed by Heikki Vatiainen) + - atmsigd allowed both sides to initiate PCR modification; Q.2963.1 only + allows the connection owner (i.e. the caller) to do this + - atmarpd no longer tries to use incoming SVCs with zero backward bandwidth + for ATMARP + - ENI and ZATM drivers didn't invoke vcc->pop on dev->ops->send failure + - make install didn't probe correctly for presence of /usr/include/stdint.h + (needed on GLIBC 1 systems) + - net/atm/resources.c didn't export bind_vcc to modules (fix by Oliver + Frommel) + - net/arpd/atmarp didn't build without make depend (reported by Stefano + Giacometti) + - clip_mkip zeroed vcc->rx_inuse and didn't take into account that clip_push + calls atm_return, which subtracts from vcc->rx_inuse too + - fixed typos in qgen/uni.h (and msg.fmt) for causes 38, 41, and 43 + - atmsigd wrote exit trace to stderr when it had a dump directory and vice + versa + - documentation still claimed that atmtcp yields messages at boot time + +New features +------------ + + - added flow to ATM VCC mapping queuing discipline (experimental) + - module for setting up ATM PVC/SVC mappings with "tc" in extra/tc (see + extra/tc/README) + - atmarpd: new request type art_query to request resolution without VC setup + - atmarp: new undocumented option -Q to test art_query + - added ATMTCP interfaces that survive disconnects (persistent; new atmtcp(8) + options -p and -r; new ioctls ATMTCP_CREATE and ATMTCP_REMOVE) + +Other changes +------------- + + - zeppelin didn't explicitly set the AAL type for outbound connections (by + Heikki Vatiainen) + - CLIP also allows SVCs to have no idle timeout at all (timeout = 0) + - moved SUNI private ioctls (SUNI_GETLOOP and SUNI_SETLOOP) from + drivers/atm/suni.h to include/linux/atm_suni.h + - atmarpd now shows QoS information for VCs where it differs from the default + or where no default is applicable + - removed the file atm/WARNING, which gave an overly pessimistic perspective + of the state of things + - switch: fab_op now returns the cause value plus (optionally) a pointer to + diagnostics in the callback instead of a simple okay/not okay indication + - updated and corrected the atmtcp man page + - further cleanup of the build procedure + - README now mainly refers to http://lrcwww.epfl.ch/linux-atm/info.html + - updated and trimmed BUGS + - added a note to CREDITS indicating its obsolescence + + Version 0.37 to 0.38 (25-JUN-1998) ==================== diff -ur --new-file old/atm/CREDITS new/atm/CREDITS --- old/atm/CREDITS Tue Nov 12 17:39:42 1996 +++ new/atm/CREDITS Tue Aug 4 20:47:23 1998 @@ -1,3 +1,9 @@ +NOTE: This file is no longer being maintained. The names of recent +contributors can be found in the CHANGES file. CREDITS may be merged +with CHANGES in the future. + +-------------------------- original content follows --------------------------- + Although many of the files carry just one name, many other people have contributed to the project in various ways, e.g. by scrutinizing parts of the implementation or by designing and implementing prototypes of diff -ur --new-file old/atm/Makefile new/atm/Makefile --- old/atm/Makefile Thu Jun 25 13:23:35 1998 +++ new/atm/Makefile Tue Aug 4 12:17:42 1998 @@ -3,7 +3,7 @@ # "maint" must appear after "qgen" DIRS=lib test debug qgen saal sigd maint arpd ilmid aqd man led lane switch - #extra + # tcd extra all: for n in $(DIRS); do $(MAKE) -C $$n || exit; done diff -ur --new-file old/atm/README new/atm/README --- old/atm/README Tue Jun 9 14:47:43 1998 +++ new/atm/README Tue Aug 4 20:43:44 1998 @@ -1,4 +1,4 @@ -ATM on Linux, release 0.38 (alpha) by Werner Almesberger, EPFL ICA +ATM on Linux, release 0.39 (alpha) by Werner Almesberger, EPFL ICA ============================================== Werner.Almesberger@epfl.ch This is experimental software. There are known major bugs and certainly @@ -11,108 +11,11 @@ The kernel patch is relative to the "standard" 2.1.105 kernel. -The following network devices are supported: - ATM over TCP pseudo device for "dry runs" - Efficient Networks ENI155p-MF/U5 155 Mbps ATM adapter - SMC ATM Power 155 - Rolf Fiedler's TNETA1570 board / UniNET1570 (*) - Zeitnet ZN1221/ZN1225 155 Mbps ATM adapter - IDT 77901/77903 ("NICStAR", 77201/77211 SAR) 155 and 25 Mbps adapters - (probably also IDT 77914/77915/77916) (*) - -The following connection types are supported: - constant bit rate (CBR) permanent connections - best-effort (UBR) permanent connections - support for UNI 3.0, 3.1, and some 4.0 unicast signaling - -The following protocols are supported: - "raw" unreliable ATM transport without AAL ("AAL0") - "raw" unreliable ATM transport over AAL5 - IP over ATM (NULL or SNAP encapsulation) - ATMARP as defined in RFC1577 (client and server) - LAN Emulation (client and server side) - Arequipa (Application REQUested IP over ATM) (*) - ANS (ATM Name Service) - -(* Not included in this version, but expected to follow soon) - -The API is based on the Linux ATM API proposed on the linux-atm mailing -list. +Please see http://lrcwww.epfl.ch/linux-atm/info.html for a list of +features supported by ATM on Linux. For usage and installation instructions, please read the file USAGE or generate the LaTeX documentation in doc/ The README in that directory explains how. For known restrictions and bugs, please read the file BUGS. - - -Performance (version 0.1) ------------ - -THIS SECTION IS VERY VERY VERY OBSOLETE AND BADLY NEEDS TO BE UPDATED. ALSO -NOTE THAT MOST OF THE THROUGHPUT MEASUREMENTS ARE TOO LOW BY 5% BECAUSE OF A -BUG IN TTCP THAT WAS ONLY DISCOVERED MUCH LATER. - -- - - - - - - - - - - - - obsolete text follows - - - - - - - - - - - - - - - -Note that version 0.10 has some debugging code enabled in the ENI driver. -It is therefore about 10% slower than indicated below. - -Platform: - - Pentium 90 MHz, Neptune and Triton PCI board, 32 MB RAM, ENI155p-MF-C - 2048 PDUs, 8192 bytes each, no wait for close - Directly connected, no switch, max buffers (128kB) allocated on board - Kernel buffers were only limited by available memory - -Results (average of ten ttcp runs): - - Transport TX Mbps RX Mbps Loss (bytes) - raw AAL5 (unchecksummed) 128-132 101 0-13% - UDP, checksummed 111-127 17- 55 49-76% (*) - UDP, unchecksummed 114-128 73- 82 27-41% - TCP (checksummed) 63- 67 63- 67 0% - -(* additional slowdown because driver printed warning messages) - -For reference, the results with the 0.0 version (average of ten ttcp -runs, only between Neptune-based PCs): - - Transport MMU hacks TX Mbps RX Mbps Loss (bytes) - raw AAL5 (unchecksummed) no 132 97 0% - yes 1607 129 0% - UDP, checksummed no 117 51 56% - UDP, unchecksummed no 118 72 39% - TCP (checksummed) no 38 38 0% - -Because ttcp does not measure the time spent in the close system call for -datagram protocols, the raw AAL5 TX rate reflects the rate at which data -can be enqueued to the device driver. - -The performance measurements are only accurate within about +-5%. Even -marginal changes can lead to a systematic change of 2-3%. - -The theoretical limits are 135.367 Mbps for raw AAL5 and 134.580 Mbps -for UDP, assuming data is sent in blocks of 8192 bytes each. - -When the Neptune-based PC was the receiving machine, transfers were -always as good or better (in terms of throughput and loss) with version -0.1 than with version 0.0. So it seems that my Triton still needs some -tuning. TCP is now pleasently fast. - - -Addendum --------- - -An early version of the ZN1221 driver yielded: - - ZN->ENI ENI->ZN - TX Mbps RX Mbps TX Mbps RX Mbps -raw AAL5 ~118 ~94 ~129 ~103 * -UDP, checksummed ~120 ~36 too many losses -TCP (checksummed) ~62 ~62 ~61 ~61 - -* ENI->ZN: RX varies between 98 and 120 Mbps - -"ZN" is a ZN1221 in a P90 Neptune, "ENI" is a ENI155p-MF-C in a P90 -Triton. Both drivers were compiled with some debugging code. diff -ur --new-file old/atm/README.DRIVERS new/atm/README.DRIVERS --- old/atm/README.DRIVERS Mon Apr 8 15:06:48 1996 +++ new/atm/README.DRIVERS Tue Aug 4 20:34:57 1998 @@ -1,5 +1,5 @@ If you're just looking for the device drivers: they're in -atm-.patch +atm.patch After applying that patch to the appropriate kernel source tree (see file USAGE for details), you'll find them in the directory diff -ur --new-file old/atm/Rules.make new/atm/Rules.make --- old/atm/Rules.make Thu Jun 18 18:33:35 1998 +++ new/atm/Rules.make Tue Aug 4 19:40:01 1998 @@ -97,6 +97,7 @@ all: [ ! -r .checker ] || $(MAKE) clean $(MAKE) do_all + for n in $(SUBDIRS); do make -C $$n || exit; done do_all: $(BOOTPGMS) $(SYSPGMS) $(USRPGMS) $(PGMS) @@ -105,6 +106,7 @@ checker: [ -r .checker ] || $(MAKE) clean $(MAKE) do_checker + @for n in $(SUBDIRS); do make -C $$n checker || exit; done do_checker: CC=checkergcc $(MAKE) -e do_all @@ -114,8 +116,10 @@ @process() { if [ ! -z "$$3" ]; then mode=$$1; dir=$$2; \ shift 2; echo "install -c -m $$mode $$* $$dir"; \ install -c -m $$mode $$* $$dir || exit 1; fi; }; \ - optprocess() { [ -z "$$3" -o -r "$$3" ] || process $$*; }; \ + optprocess() { [ -z "$$3" -o -r "$$2/$$3" ] || \ + process $$*; }; \ $(PROCLIST) + @for n in $(SUBDIRS); do make -C $$n install || exit; done # optprocess is only defined for a single file. Right now we're using it only # for stdint.h @@ -126,6 +130,7 @@ install -d $$2 || exit 1; fi; }; \ optprocess() { :; }; \ $(PROCLIST) + @for n in $(SUBDIRS); do make -C $$n instdirs || exit; done uninstall: @process() { if [ ! -z "$$3" ]; then dir=$$2; shift 2; \ @@ -133,22 +138,28 @@ cd $$dir; rm -f $$*; fi; }; \ optprocess() { :; }; \ $(PROCLIST) + @for n in $(SUBDIRS); do make -C $$n uninstall || exit; done filenames: @process() { if [ ! -z "$$3" ]; then dir=$$2; shift 2; \ for n in $$*; do echo $$dir/$$n; done; fi; }; \ optprocess() { process $$*; }; \ $(PROCLIST) + @for n in $(SUBDIRS); do make -C $$n filenames || exit; done depend: $(CPP) -M *.c $(INCLUDES) -I$(TOPDIR)/lib >.tmpdepend mv .tmpdepend .depend + for n in $(SUBDIRS); do make -C $$n depend || exit; done clean: rm -f *.o core .checker y.tab.h y.tab.c lex.yy.c $(TRASH) + for n in $(SUBDIRS); do make -C $$n clean || exit; done spotless: clean - rm -f $(BOOTPGMS) $(SYSPGMS) $(USRPGMS) $(PGMS) *.a .depend + rm -f $(BOOTPGMS) $(SYSPGMS) $(USRPGMS) $(PGMS) *.a + rm -f .depend .checker + for n in $(SUBDIRS); do make -C $$n spotless || exit; done lex.yy.o: lex.yy.c y.tab.h $(CC) -c $(CFLAGS_LEX) lex.yy.c diff -ur --new-file old/atm/USAGE new/atm/USAGE --- old/atm/USAGE Thu Jun 25 14:13:40 1998 +++ new/atm/USAGE Tue Aug 4 21:15:42 1998 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.38 +Usage instructions - ATM on Linux, release 0.39 ------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -17,7 +17,7 @@ In order to install this package, you need - the package itself - ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.38.tar.gz + ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.39.tar.gz - the Linux kernel, version 2.1.105, e.g. from ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.105.tar.gz - Perl, version 4 or 5 @@ -33,7 +33,7 @@ all the files listed above there. Then extract the ATM on Linux distribution: -tar xfz atm-0.38.tar.gz +tar xfz atm-0.39.tar.gz and the kernel source: @@ -97,11 +97,6 @@ Driver messages --------------- -If you've configured the ATM over TCP driver, you should see eight lines -like this one: - -atmtcp(itf 1): ready - If you've configured the ENI155p-MF driver, you should see two lines like these: @@ -118,6 +113,10 @@ Note that your board needs to be at least at revision level 3 if you want to use it in a Triton-based system. + +Note that if you've configured only the ATM over TCP driver, there are no +messages at startup, because ATM over TCP devices are created later using +the atmtcp command. Memory debugging diff -ur --new-file old/atm/VERSION new/atm/VERSION --- old/atm/VERSION Tue Jun 9 14:47:22 1998 +++ new/atm/VERSION Tue Aug 4 20:31:03 1998 @@ -1 +1 @@ -0.38 +0.39 diff -ur --new-file old/atm/WARNING new/atm/WARNING --- old/atm/WARNING Thu Aug 14 20:22:51 1997 +++ new/atm/WARNING Thu Jan 1 01:00:00 1970 @@ -1,5 +0,0 @@ -WARNING: This release is incomplete and contains lots of known bugs. The - documentation has not been updated and may be highly misleading. - The only purpose of this release is to keep people synchronized. - A more stable version which will actually do something useful - will follow later. diff -ur --new-file old/atm/arpd/Makefile new/atm/arpd/Makefile --- old/atm/arpd/Makefile Fri Jun 5 18:29:45 1998 +++ new/atm/arpd/Makefile Tue Aug 4 19:35:54 1998 @@ -9,5 +9,8 @@ include ../Rules.make +atmarp: atmarp.o + $(CC) $(LDFLAGS) -o atmarp atmarp.o $(LIBS) $(LDLIBS) + atmarpd: $(OBJS) $(CC) $(LDFLAGS) -o atmarpd $(OBJS) $(LIBS) $(LDLIBS) diff -ur --new-file old/atm/arpd/arp.c new/atm/arpd/arp.c --- old/atm/arpd/arp.c Tue Jun 9 14:43:25 1998 +++ new/atm/arpd/arp.c Tue Jul 28 16:14:18 1998 @@ -67,7 +67,8 @@ { if (do_close(vcc->fd)) diag(COMPONENT,DIAG_ERROR,"close: %s",strerror(errno)); - Q_REMOVE(vcc->entry->vccs,vcc); + if (vcc->entry) Q_REMOVE(vcc->entry->vccs,vcc); + else Q_REMOVE(unidirectional_vccs,vcc); free(vcc); } @@ -85,6 +86,8 @@ void discard_entry(ENTRY *entry) { + if (entry->notify) + diag(COMPONENT,DIAG_FATAL,"discard_entry: entry %p had notifications"); STOP_TIMER(entry); discard_vccs(entry); if (!entry->itf) Q_REMOVE(unknown_incoming,entry); @@ -105,7 +108,7 @@ */ -static int want_arp_srv(ITF *itf) +static int want_arp_srv(const ITF *itf) { VCC *vcc; int fd; @@ -238,7 +241,7 @@ } -static void inarp_for_itf(VCC *vcc,ITF *itf) +static void inarp_for_itf(const VCC *vcc,const ITF *itf) { if (itf->local_ip) { diag(COMPONENT,DIAG_DEBUG," for itf %d",itf->number); @@ -297,6 +300,18 @@ } +static void send_notifications(ENTRY *entry,int success) +{ + NOTIFY *this; + + while ((this = entry->notify)) { + entry->notify = this->next; + notify(&this->ctx,entry->ip,success ? entry : NULL); + free(this); + } +} + + static void timer_expiration(void *user); @@ -341,6 +356,7 @@ entry->timer = NULL; switch (entry->state) { case as_resolv: + send_notifications(entry,0); if ((entry->flags & ATF_ARPSRV) && !entry->vccs) { if (entry->itf) want_arp_srv(entry->itf); break; @@ -473,6 +489,7 @@ free(vcc->entry); vcc->entry = entry; Q_INSERT_HEAD(entry->vccs,vcc); + entry->flags &= ~ATF_NOVC; assert(!vcc->connecting); if (set_ip(vcc->fd,ip) < 0) diag(COMPONENT,DIAG_ERROR,"set_ip: %s",strerror(errno)); @@ -509,6 +526,7 @@ && atm_equal((struct sockaddr *) entry->addr,(struct sockaddr *) addr,0, 0)))) return; /* no news */ STOP_TIMER(entry); + if (entry->ip != ip) send_notifications(entry,0); entry->ip = ip; if (!entry->itf) { entry->itf = itf; @@ -543,8 +561,11 @@ if (!walk->connecting) if (set_ip(walk->fd,ip) < 0) diag(COMPONENT,DIAG_ERROR,"set_ip: %s",strerror(errno)); - if (entry->state != as_valid && !entry->vccs && itf->arp_srv) - connect_me(entry); + if (entry->state != as_valid) { + if (!entry->vccs && itf->arp_srv && !(entry->flags & ATF_NOVC)) + connect_me(entry); + send_notifications(entry,1); + } if ((entry->flags & ATF_ARPSRV) || !(entry->flags & ATF_PERM)) if (entry->itf->arp_srv) START_TIMER(entry,CREVAL); else START_TIMER(entry,SREVAL); @@ -562,12 +583,55 @@ if (!itf) return; entry = lookup_ip(itf,ip); if (!entry || entry->state != as_resolv) return; + send_notifications(entry,0); if (entry->flags & ATF_PERM) return; - if (entry->vccs || (entry->flags & ATF_PERM)) entry->state = as_invalid; + if (entry->vccs) entry->state = as_invalid; else discard_entry(entry); } +/* + * Returns: + * <0 resolution is not possible (*entry may be clobbered) + * 0 resolution has succeeded (entry in *entry) + * >0 resolution is proceeding (entry in *entry) + */ + +static int resolve(ITF *itf,uint32_t ip,ENTRY **entry,int want_vc) +{ + *entry = lookup_ip(itf,ip); + if ((!*entry || (*entry)->state != as_valid) && !itf->arp_srv) + return -1; /* bad luck - no ARP server when we need one */ + if (*entry) { + if (want_vc) (*entry)->flags &= ~ATF_NOVC; + switch ((*entry)->state) { + case as_resolv: + return 1; /* somebody else is already taking care of that */ + case as_valid: + if (!(*entry)->vccs && !((*entry)->flags & ATF_NOVC)) + connect_me(*entry); + return 0; + case as_invalid: + if ((*entry)->svc && (*entry)->itf && (*entry)->itf->arp_srv && + !((*entry)->flags & ATF_ARPSRV)) break; + return -1; + default: + diag(COMPONENT,DIAG_FATAL,"bad state %d",(*entry)->state); + } + } + else { + *entry = alloc_entry(1); + (*entry)->flags = ATF_PUBL | (want_vc ? 0 : ATF_NOVC); + (*entry)->ip = ip; + (*entry)->itf = itf; + Q_INSERT_HEAD(itf->table,*entry); + (*entry)->qos = itf->qos; + } + revalidate(*entry); + return 1; +} + + void need_ip(int itf_num,uint32_t ip) { ITF *itf; @@ -580,32 +644,40 @@ diag(COMPONENT,DIAG_ERROR,"itf %d not found",itf_num); return; } - entry = lookup_ip(itf,ip); - if ((!entry || entry->state != as_valid) && !itf->arp_srv) - return; /* bad luck - no ARP server when we need one */ - if (entry) - switch (entry->state) { - case as_resolv: - return; /* somebody else is already taking care of that */ - case as_valid: - if (!entry->vccs) connect_me(entry); - return; - case as_invalid: - if (entry->svc && entry->itf && entry->itf->arp_srv && - !(entry->flags & ATF_ARPSRV)) break; - return; - default: - diag(COMPONENT,DIAG_FATAL,"bad state %d",entry->state); - } - else { - entry = alloc_entry(1); - entry->flags = ATF_PUBL; - entry->ip = ip; - entry->itf = itf; - Q_INSERT_HEAD(itf->table,entry); - entry->qos = itf->qos; + (void) resolve(itf,ip,&entry,1); +} + + +void query_ip(const UN_CTX *ctx,uint32_t ip) +{ + ITF *itf; + ENTRY *entry; + NOTIFY *notifier; + int result; + + diag(COMPONENT,DIAG_DEBUG,"query for %d.%d.%d.%d", + ((unsigned char *) &ip)[0],((unsigned char *) &ip)[1], + ((unsigned char *) &ip)[2],((unsigned char *) &ip)[3]); + if (!(itf = lookup_itf_by_ip(ip))) { + diag(COMPONENT,DIAG_WARN,"itf for %d.%d.%d.%d not found", + ((unsigned char *) &ip)[0],((unsigned char *) &ip)[1], + ((unsigned char *) &ip)[2],((unsigned char *) &ip)[3]); + notify(ctx,ip,NULL); + return; } - revalidate(entry); + result = resolve(itf,ip,&entry,0); + if (result < 0) { + notify(ctx,ip,NULL); + return; + } + if (!result) { + notify(ctx,ip,entry); + return; + } + notifier = alloc_t(NOTIFY); + notifier->ctx = *ctx; + notifier->next = entry->notify; + entry->notify = notifier; } @@ -819,10 +891,12 @@ return -ENOENT; } if ((flags ^ entry->flags) & ATF_ARPSRV) return -EINVAL; + send_notifications(entry,0); if ((entry->flags & ATF_ARPSRV) && entry->itf) for (walk = entry->itf->table; walk; walk = next) { next = walk->next; - if (walk != entry && walk->state == as_resolv) + if (walk != entry && walk->state == as_resolv) { + send_notifications(walk,0); if (!walk->vccs && !(walk->flags & ATF_PERM)) /* PERM is rather unlikely here, since this would be a second ARP server (only ARP servers can go as_resolv if @@ -832,6 +906,7 @@ STOP_TIMER(walk); walk->state = as_invalid; } + } } discard_entry(entry); return 0; @@ -953,4 +1028,11 @@ diag(COMPONENT,DIAG_DEBUG,"incoming VCC 0x%p",vcc); START_TIMER(vcc->entry,REPLY); inarp_request(vcc->entry); +} + + +void incoming_unidirectional(VCC *vcc) +{ + diag(COMPONENT,DIAG_DEBUG,"incoming unidirectional VCC 0x%p",vcc); + /* don't put it into ATMARP table */ } diff -ur --new-file old/atm/arpd/arp.h new/atm/arpd/arp.h --- old/atm/arpd/arp.h Sat Jun 6 01:18:43 1998 +++ new/atm/arpd/arp.h Tue Jul 28 15:46:28 1998 @@ -9,6 +9,7 @@ #include #include +#include "atmd.h" #include "atmarp.h" #include "atmarpd.h" #include "table.h" @@ -18,11 +19,13 @@ void discard_entry(ENTRY *entry); void vcc_detach(ENTRY *entry); void need_ip(int itf_num,uint32_t ip); +void query_ip(const UN_CTX *ctx,uint32_t ip); void incoming_arp(VCC *vcc,struct atmarphdr *hdr,int len); int arp_ioctl(struct atmarp_req *req); void vcc_connected(VCC *vcc); void vcc_failed(VCC *vcc); void disconnect_vcc(VCC *vcc); void incoming_call(VCC *vcc); +void incoming_unidirectional(VCC *vcc); #endif diff -ur --new-file old/atm/arpd/atmarp.c new/atm/arpd/atmarp.c --- old/atm/arpd/atmarp.c Sat Jun 6 02:18:27 1998 +++ new/atm/arpd/atmarp.c Tue Jul 28 16:02:48 1998 @@ -27,9 +27,26 @@ #define BUF_SIZE 4096 +static int query_result(struct atmarp_req *reply) +{ + unsigned char *ipp = (unsigned char *) &reply->ip; + char buf[MAX_ATM_ADDR_LEN+1]; + int error; + + printf("IP: %d.%d.%d.%d\n",ipp[0],ipp[1],ipp[2],ipp[3]); + if (!atmsvc_addr_in_use(reply->addr)) return 0; + error = atm2text(buf,sizeof(buf),(struct sockaddr *) &reply->addr, + A2T_PRETTY | A2T_NAME) < 0; + if (error) strcpy(buf,""); + printf("ATM: %s\n",buf); + return error ? 1 : 0; +} + + static int send_request(struct atmarp_req *req) { - int s,len,reply; + struct atmarp_req reply; + int s,len; s = un_attach(ATMARP_SOCKET_PATH); if (s < 0) { @@ -45,15 +62,16 @@ perror("read"); exit(1); } - if (len != sizeof(reply)) { - fprintf(stderr,"bad read: %d != %d\n",len,sizeof(reply)); + if (req->type == art_query) return query_result(&reply); + if (len != sizeof(int)) { + fprintf(stderr,"bad read: %d != %d\n",len,sizeof(int)); exit(1); } - if (reply < 0) { - fprintf(stderr,"atmarp: %s\n",strerror(-reply)); + if (*(int *) &reply < 0) { + fprintf(stderr,"atmarp: %s\n",strerror(-*(int *) &reply)); exit(1); } - return reply; + return *(int *) &reply; } @@ -90,6 +108,9 @@ fprintf(stderr,"%6s %s -s ip_addr atm_addr [pcr value] [qos spec] [temp] " "[pub] [arpsrv]\n","",name); fprintf(stderr,"%6s %s -d ip_addr [arpsrv]\n","",name); +#if 0 /* undocumented */ + fprintf(stderr,"%6s %s -Q ip_addr\n","",name); +#endif exit(1); } @@ -102,7 +123,7 @@ char *here,*end; req.type = 0; - while ((c = getopt(argc,argv,"acdqs")) != EOF) + while ((c = getopt(argc,argv,"acdqQs")) != EOF) switch (c) { case 'a': if (argc != optind || req.type) usage(argv[0]); @@ -113,17 +134,21 @@ if (req.type) usage(argv[0]); req.type = art_create; break; + case 'd': + if (req.type) usage(argv[0]); + req.type = art_delete; + break; case 'q': if (req.type) usage(argv[0]); req.type = art_qos; break; - case 's': + case 'Q': if (req.type) usage(argv[0]); - req.type = art_set; + req.type = art_query; break; - case 'd': + case 's': if (req.type) usage(argv[0]); - req.type = art_delete; + req.type = art_set; break; default: usage(argv[0]); @@ -149,6 +174,9 @@ /* fall through */ case art_set: if (argc < optind+2) usage(argv[0]); + break; + case art_query: + if (argc != optind+1) usage(argv[0]); break; case art_delete: if (argc < optind+1) usage(argv[0]); diff -ur --new-file old/atm/arpd/atmarpd.c new/atm/arpd/atmarpd.c --- old/atm/arpd/atmarpd.c Sat Jun 6 02:20:20 1998 +++ new/atm/arpd/atmarpd.c Fri Jul 17 14:38:47 1998 @@ -28,6 +28,8 @@ ITF *itfs = NULL; ENTRY *unknown_incoming = NULL; +VCC *unidirectional_vccs = NULL; + int debug; int pretty = A2T_PRETTY | A2T_NAME | A2T_LOCAL; int merge = 0; diff -ur --new-file old/atm/arpd/atmarpd.h new/atm/arpd/atmarpd.h --- old/atm/arpd/atmarpd.h Sat Apr 11 13:01:13 1998 +++ new/atm/arpd/atmarpd.h Tue Jul 28 19:41:24 1998 @@ -6,6 +6,7 @@ #define _ATMARPD_H #include +#include #define ATMARP_SOCKET_PATH "/dev/atmarp" /* it seems awfully silly to @@ -20,6 +21,7 @@ #define ATF_NULL 0x1000 /* use NULL encapsulation */ #define ATF_ARPSRV 0x2000 /* entry describes ARP server */ +#define ATF_NOVC 0x4000 /* query only; do not create a VC */ enum atmarp_req_type { @@ -28,7 +30,8 @@ art_qos, /* set the default QoS */ art_set, /* create or change an entry */ art_delete, /* delete an entry */ - art_table /* update the ATMARP table file */ + art_table, /* update the ATMARP table file */ + art_query /* request resolution without VC setup */ }; struct atmarp_req { diff -ur --new-file old/atm/arpd/io.c new/atm/arpd/io.c --- old/atm/arpd/io.c Tue Jun 9 14:43:33 1998 +++ new/atm/arpd/io.c Tue Jul 28 15:52:17 1998 @@ -130,43 +130,56 @@ } -static int got_unix(void *buf,int len,void *user) +void notify(const UN_CTX *ctx,uint32_t ip,const ENTRY *entry) { - struct atmarp_req *req = buf; - int *reply = buf; + struct atmarp_req reply; - if (len != sizeof(*req)) { - diag(COMPONENT,DIAG_ERROR,"bad unix read: %d != %d",len,sizeof(*req)); - return 0; + memset(&reply,0,sizeof(reply)); + reply.type = art_query; + reply.ip = ip; + if (entry) reply.addr = *entry->addr; + if (un_send(ctx,&reply,sizeof(reply)) < 0) + diag(COMPONENT,DIAG_WARN,"notify: %s",strerror(errno)); +} + + +static void recv_unix(void) +{ + UN_CTX ctx; + struct atmarp_req req; + int len,reply; + + len = un_recv(&ctx,unix_sock,&req,sizeof(req)); + if (len < 0) { + diag(COMPONENT,DIAG_ERROR,"recv_unix: %s",strerror(errno)); + return; + } + if (len != sizeof(req)) { + diag(COMPONENT,DIAG_ERROR,"bad unix read: %d != %d",len,sizeof(req)); + return; } - switch (req->type) { + switch (req.type) { case art_create: - *reply = ioctl(kernel,SIOCMKCLIP,req->itf); - if (*reply >= 0) itf_create(*reply); + reply = ioctl(kernel,SIOCMKCLIP,req.itf); + if (reply >= 0) itf_create(reply); break; case art_qos: case art_set: case art_delete: - *reply = arp_ioctl(req); + reply = arp_ioctl(&req); break; case art_table: - *reply = table_update(); + reply = table_update(); break; + case art_query: + query_ip(&ctx,req.ip); + return; default: - diag(COMPONENT,DIAG_ERROR,"invalid request msg type 0x%x", - req->type); - *reply = -EINVAL; + diag(COMPONENT,DIAG_ERROR,"invalid request msg type 0x%x",req.type); + reply = -EINVAL; } - return sizeof(int); -} - - -static void recv_unix(void) -{ - struct atmarp_req req; - - if (un_reply(unix_sock,&req,sizeof(req),got_unix,NULL) < 0) - diag(COMPONENT,DIAG_ERROR,"un_reply: %s",strerror(errno)); + if (un_send(&ctx,&reply,sizeof(reply)) < 0) + diag(COMPONENT,DIAG_ERROR,"un_send: %s",strerror(errno)); } @@ -221,13 +234,45 @@ } +static void drain_vcc(VCC *vcc) +{ + unsigned char buffer[MAX_BUFFER]; + char line[80]; /* actually, it's only 7+16*3+1 */ + int size; + int i; + + size = read(vcc->fd,buffer,MAX_BUFFER); + if (!size) { + disconnect_vcc(vcc); + return; + } + if (size < 0) { + diag(COMPONENT,DIAG_ERROR,"read vcc: %s",strerror(errno)); + disconnect_vcc(vcc); + return; + } + diag(COMPONENT,DIAG_WARN,"drain_vcc: unexpected message on " + "unidirectional (RSVP?) VCC %p:",vcc); + for (i = 0; i < size; i++) { + if (!(i & 15)) { + if (i) diag(COMPONENT,DIAG_WARN,"%s",line); + sprintf(line," %04x:",i); + *line = 0; + } + sprintf(strchr(line,0)," %02x",buffer[i]); + } + diag(COMPONENT,DIAG_WARN,"%s",line); +} + + static void accept_new(void) { char buffer[MAX_ATM_ADDR_LEN+1]; struct sockaddr_atmsvc addr; + struct atm_qos qos; ENTRY *entry; VCC *vcc; - int fd,len,error; + int fd,len,size,error; len = sizeof(addr); if ((fd = accept(incoming,(struct sockaddr *) &addr,&len)) < 0) { @@ -240,7 +285,17 @@ } return; } - if (ioctl(fd,ATMARP_MKIP,CLIP_DEFAULT_IDLETIMER) < 0) { + /* the following code probably belongs to arp.c ... */ + if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) &addr,pretty) < + 0) strcpy(buffer,""); + diag(COMPONENT,DIAG_DEBUG,"Incoming call from %s",buffer); + size = sizeof(qos); + if (getsockopt(fd,SOL_ATM,SO_ATMQOS,&qos,&size) < 0) + diag(COMPONENT,DIAG_FATAL,"getsockopt SO_ATMQOS: %s",strerror(errno)); + if (size != sizeof(qos)) + diag(COMPONENT,DIAG_FATAL,"SO_ATMQOS: size %d != %d",size,sizeof(qos)); + if (ioctl(fd,ATMARP_MKIP,qos.txtp.traffic_class == ATM_NONE ? 0 : + CLIP_DEFAULT_IDLETIMER) < 0) { diag(COMPONENT,DIAG_ERROR,"ioctl ATMARP_MKIP: %s",strerror(errno)); (void) do_close(fd); return; @@ -249,10 +304,12 @@ vcc->active = 0; vcc->connecting = 0; vcc->fd = fd; - /* the following code probably belongs to arp.c ... */ - if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) &addr,pretty) < - 0) strcpy(buffer,""); - diag(COMPONENT,DIAG_DEBUG,"Incoming call from %s",buffer); + if (qos.txtp.traffic_class == ATM_NONE) { + vcc->entry = NULL; + incoming_unidirectional(vcc); + Q_INSERT_HEAD(unidirectional_vccs,vcc); + return; + } if (merge) { ITF *itf; @@ -406,6 +463,10 @@ FD_SET(entry->vccs->fd,&rset); if (entry->vccs->fd >= fds) fds = entry->vccs->fd+1; } + for (vcc = unidirectional_vccs; vcc; vcc = vcc->next) { + FD_SET(vcc->fd,&rset); + if (vcc->fd >= fds) fds = vcc->fd+1; + } ret = select(fds,&rset,&cset,NULL,next_timer()); /* * Now here's something strange: < 0.32 needed the exception mask to be NULL @@ -452,6 +513,10 @@ for (entry = unknown_incoming; entry; entry = next_entry) { next_entry = entry->next; if (FD_ISSET(entry->vccs->fd,&rset)) recv_vcc(entry->vccs); + } + for (vcc = unidirectional_vccs; vcc; vcc = next_vcc) { + next_vcc = vcc->next; + if (FD_ISSET(vcc->fd,&rset)) drain_vcc(vcc); } expire_timers(); /* expire timers after handling messages to make sure we don't diff -ur --new-file old/atm/arpd/io.h new/atm/arpd/io.h --- old/atm/arpd/io.h Tue Jun 9 14:43:40 1998 +++ new/atm/arpd/io.h Tue Jul 28 15:47:52 1998 @@ -9,10 +9,14 @@ #include #include /* for struct sockaddr */ #include /* for struct sockaddr_atmsvc */ +#include + +#include "table.h" void open_all(void); void close_all(void); +void notify(const UN_CTX *ctx,uint32_t ip,const ENTRY *entry); int do_close(int fd); void poll_loop(void); int connect_vcc(struct sockaddr *remote,const struct atm_qos *qos,int timeout); diff -ur --new-file old/atm/arpd/table.c new/atm/arpd/table.c --- old/atm/arpd/table.c Thu Jun 18 03:20:55 1998 +++ new/atm/arpd/table.c Tue Jul 28 16:19:02 1998 @@ -37,6 +37,7 @@ entry->flags = 0; entry->timer = NULL; entry->vccs = NULL; + entry->notify = NULL; entry->itf = NULL; return entry; } @@ -94,13 +95,15 @@ static void dump_vcc(VCC *vcc) { struct sockaddr_atmsvc addr; - char buffer[MAX_ATM_ADDR_LEN+1]; + char addr_buf[MAX_ATM_ADDR_LEN+1]; + char qos_buf[MAX_ATM_QOS_LEN+1]; + struct atm_qos qos; int size; size = sizeof(addr); if (getpeername(vcc->fd,(struct sockaddr *) &addr,&size) < 0) { diag(COMPONENT,DIAG_ERROR,"getpeername: %s",strerror(errno)); - strcpy(buffer,""); + strcpy(addr_buf,""); } else { #if 0 @@ -110,11 +113,31 @@ printf("%02X ",((unsigned char *) &addr)[i]); printf("\n"); #endif - if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) &addr, - pretty) < 0) strcpy(buffer,""); + if (atm2text(addr_buf,sizeof(addr_buf),(struct sockaddr *) &addr, + pretty) < 0) strcpy(addr_buf,""); + } + output(" %s%s",addr_buf,vcc->connecting ? ", connecting" : + !vcc->entry || !vcc->entry->svc ? "" : vcc->active ? " (active)" : + " (passive)"); + if (vcc->connecting) return; + size = sizeof(qos); + if (getsockopt(vcc->fd,SOL_ATM,SO_ATMQOS,&qos,&size) < 0) + sprintf(qos_buf,"",strerror(errno)); + else { + if (vcc->entry && qos_equal(&vcc->entry->qos,&qos)) return; + if (qos2text(qos_buf,sizeof(qos_buf),&qos,0) < 0) + strcpy(qos_buf,""); + output(" QOS: %s",qos_buf); + } +} + + +static void dump_vccs(VCC *vcc) +{ + while (vcc) { + dump_vcc(vcc); + vcc = vcc->next; } - output(" %s%s",buffer,vcc->connecting ? ", connecting" : - !vcc->entry->svc ? "" : vcc->active ? " (active)" : " (passive)"); } @@ -124,10 +147,9 @@ "???", "com", "PERM", "PUBL", /* 0x0001-0x0008 */ "trailers", "netmask", "dontpub", "magic", /* 0x0010-0x0080 */ "???", "???", "???", "???", /* 0x0100-0x0800 */ - "NULL", "ARPSRV", "???" }; /* 0x1000-0x8000 */ + "NULL", "ARPSRV", "NOVC" }; /* 0x1000-0x8000 */ /* lower case flags are not used by ATMARP */ ENTRY *entry; - VCC *vcc; char addr_buf[MAX_ATM_ADDR_LEN+1]; char qos_buf[MAX_ATM_QOS_LEN+1]; char tmp[100]; /* large enough for all flags */ @@ -152,9 +174,17 @@ if (entry->itf && !qos_equal(&entry->itf->qos,&entry->qos)) { if (qos2text(qos_buf,sizeof(qos_buf),&entry->qos,0) < 0) strcpy(qos_buf,""); - output(" QOS: %s",qos_buf); + output(" QOS: %s",qos_buf); } - for (vcc = entry->vccs; vcc; vcc = vcc->next) dump_vcc(vcc); + if (entry->notify) { + NOTIFY *notify; + int count; + + count = 0; + for (notify = entry->notify; notify; notify = notify->next) count++; + output(" %d quer%s pending",count,count == 1 ? "y" : "ies"); + } + dump_vccs(entry->vccs); } } @@ -181,9 +211,9 @@ for (itf = itfs; itf; itf = itf->next) dump_itf(itf); output("----- Unknown incoming connections -----"); dump_entries(unknown_incoming); + output("----- Incoming unidirectional connections -----"); + dump_vccs(unidirectional_vccs); output("----- End of dump -----"); - if (out_file) { - } } diff -ur --new-file old/atm/arpd/table.h new/atm/arpd/table.h --- old/atm/arpd/table.h Sat Apr 11 12:11:56 1998 +++ new/atm/arpd/table.h Tue Jul 28 15:51:33 1998 @@ -28,6 +28,11 @@ as_valid, /* valid */ } ADDR_STATE; +typedef struct _notify { + UN_CTX ctx; /* peer to send reply to */ + struct _notify *next; +} NOTIFY; + typedef struct _entry { ADDR_STATE state; int svc; @@ -38,7 +43,8 @@ TIMER *timer; /* currently active timer or NULL */ int timeout; /* current interval - only necessary if using retries */ int retries; - struct _vcc *vccs; + VCC *vccs; + NOTIFY *notify; struct _itf *itf; struct _entry *prev,*next; /* undefined if itf == NULL */ } ENTRY; @@ -66,6 +72,7 @@ extern ITF *itfs; extern ENTRY *unknown_incoming; +extern VCC *unidirectional_vccs; extern int pretty,merge; diff -ur --new-file old/atm/atm.patch new/atm/atm.patch --- old/atm/atm.patch Thu Jun 25 14:13:22 1998 +++ new/atm/atm.patch Tue Aug 4 21:15:30 1998 @@ -293,8 +293,8 @@ + return devs; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/atmtcp.c Wed Jun 24 19:27:22 1998 -@@ -0,0 +1,226 @@ ++++ work/drivers/atm/atmtcp.c Tue Aug 4 19:07:09 1998 +@@ -0,0 +1,311 @@ +/* drivers/atm/atmtcp.c - ATM over TCP "device" driver */ + +/* Written 1997,1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -303,9 +303,17 @@ +#include +#include +#include -+#include "../../net/atm/tunable.h" /* fix this */ -+#include "../../net/atm/protocols.h" /* fix this */ -+#include "../../net/atm/resources.h" /* fix this */ ++#include "../../net/atm/tunable.h" /* @@@ fix this */ ++#include "../../net/atm/protocols.h" /* @@@ fix this */ ++ ++ ++#define PRIV(dev) ((struct atmtcp_dev_data *) ((dev)->dev_data)) ++ ++ ++struct atmtcp_dev_data { ++ struct atm_vcc *vcc; /* control VCC; NULL if detached */ ++ int persist; /* non-zero if persistent */ ++}; + + +#define DEV_LABEL "atmtcp" @@ -361,15 +369,18 @@ + +static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) +{ ++ struct atmtcp_dev_data *dev_data; + struct atm_vcc *out_vcc; + struct sk_buff *new_skb; + struct atmtcp_hdr *hdr; + int size; + -+ out_vcc = vcc->dev->dev_data; -+ if (!out_vcc) { ++ dev_data = PRIV(vcc->dev); ++ if (dev_data) out_vcc = dev_data->vcc; ++ if (!dev_data || !out_vcc) { + if (vcc->pop) vcc->pop(vcc,skb); + else dev_kfree_skb(skb); ++ if (dev_data) return 0; + vcc->stats->tx_err++; + return -ENOLINK; + } @@ -398,10 +409,28 @@ +} + + ++static int atmtcp_v_proc(struct atm_dev *dev,loff_t *pos,char *page) ++{ ++ struct atmtcp_dev_data *dev_data = PRIV(dev); ++ ++ if (*pos) return 0; ++ if (!dev_data->persist) return sprintf(page,"ephemeral\n"); ++ return sprintf(page,"persistent, %sconnected\n", ++ dev_data->vcc ? "" : "dis"); ++} ++ ++ +static void atmtcp_c_close(struct atm_vcc *vcc) +{ -+ ((struct atm_dev *) vcc->dev_data)->dev_data = NULL; -+ shutdown_atm_dev(vcc->dev_data); ++ struct atm_dev *atmtcp_dev; ++ struct atmtcp_dev_data *dev_data; ++ ++ atmtcp_dev = (struct atm_dev *) vcc->dev_data; ++ dev_data = PRIV(atmtcp_dev); ++ dev_data->vcc = NULL; ++ if (dev_data->persist) return; ++ kfree(dev_data); ++ shutdown_atm_dev(atmtcp_dev); + vcc->dev_data = NULL; +} + @@ -465,7 +494,8 @@ + NULL, /* no phy_get */ + NULL, /* no feedback */ + NULL, /* no change_qos */ -+ NULL /* no free_rx_skb */ ++ NULL, /* no free_rx_skb */ ++ atmtcp_v_proc /* proc_read */ +}; + + @@ -488,11 +518,12 @@ + NULL, /* no phy_get */ + NULL, /* no feedback */ + NULL, /* no change_qos */ -+ NULL /* no free_rx_skb */ ++ NULL, /* no free_rx_skb */ ++ NULL /* no proc_read */ +}; + + -+static struct atm_dev atmtcp_dev = { ++static struct atm_dev atmtcp_control_dev = { + &atmtcp_c_dev_ops, + NULL, /* no PHY */ + "atmtcp", /* type */ @@ -505,25 +536,79 @@ +}; + + -+int atmtcp_attach(struct atm_vcc *vcc,int itf) ++static int atmtcp_create(int itf,int persist,struct atm_dev **result) +{ ++ struct atmtcp_dev_data *dev_data; + struct atm_dev *dev; + ++ dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL); ++ if (!dev_data) return -ENOMEM; + dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,0); -+ if (!dev) return itf == -1 ? -ENOMEM : -EBUSY; ++ if (!dev) { ++ kfree(dev_data); ++ return itf == -1 ? -ENOMEM : -EBUSY; ++ } + dev->ci_range.vpi_bits = MAX_VPI_BITS; + dev->ci_range.vci_bits = MAX_VCI_BITS; -+ dev->dev_data = vcc; -+ bind_vcc(vcc,&atmtcp_dev); ++ PRIV(dev) = dev_data; ++ PRIV(dev)->vcc = NULL; ++ PRIV(dev)->persist = persist; ++ if (result) *result = dev; ++ return 0; ++} ++ ++ ++int atmtcp_attach(struct atm_vcc *vcc,int itf) ++{ ++ struct atm_dev *dev; ++ ++ dev = NULL; ++ if (itf != -1) dev = atm_find_dev(itf); ++ if (dev) { ++ if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE; ++ if (PRIV(dev)->vcc) return -EBUSY; ++ } ++ else { ++ int error; ++ ++ error = atmtcp_create(itf,0,&dev); ++ if (error) return error; ++ } ++ PRIV(dev)->vcc = vcc; ++ bind_vcc(vcc,&atmtcp_control_dev); + vcc->flags |= ATM_VF_READY | ATM_VF_META; + vcc->dev_data = dev; + (void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */ -+ vcc->stats = &atmtcp_dev.stats.aal5; ++ vcc->stats = &atmtcp_control_dev.stats.aal5; + return dev->number; +} ++ ++ ++int atmtcp_create_persistent(int itf) ++{ ++ return atmtcp_create(itf,1,NULL); ++} ++ ++ ++int atmtcp_remove_persistent(int itf) ++{ ++ struct atm_dev *dev; ++ struct atmtcp_dev_data *dev_data; ++ ++ dev = atm_find_dev(itf); ++ if (!dev) return -ENODEV; ++ if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE; ++ dev_data = PRIV(dev); ++ if (!dev_data->persist) return 0; ++ dev_data->persist = 0; ++ if (PRIV(dev)->vcc) return 0; ++ kfree(dev_data); ++ shutdown_atm_dev(dev); ++ return 0; ++} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/eni.c Thu Jun 18 19:04:24 1998 -@@ -0,0 +1,2140 @@ ++++ work/drivers/atm/eni.c Fri Jul 17 16:38:52 1998 +@@ -0,0 +1,2143 @@ +/* drivers/atm/eni.c - Efficient Networks ENI155P device driver */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -2467,17 +2552,20 @@ + + DPRINTK(">eni_send\n"); + if (!ENI_VCC(vcc)->tx) { -+ dev_kfree_skb(skb); ++ if (vcc->pop) vcc->pop(vcc,skb); ++ else dev_kfree_skb(skb); + return -EINVAL; + } + if (!skb) { + printk(KERN_CRIT "!skb in eni_send ?\n"); -+ dev_kfree_skb(skb); ++ if (vcc->pop) vcc->pop(vcc,skb); ++ else dev_kfree_skb(skb); + return -EINVAL; + } + if (vcc->qos.aal == ATM_AAL0) { + if (skb->len != ATM_CELL_SIZE-1) { -+ dev_kfree_skb(skb); ++ if (vcc->pop) vcc->pop(vcc,skb); ++ else dev_kfree_skb(skb); + return -EINVAL; + } + *(u32 *) skb->data = htonl(*(u32 *) skb->data); @@ -2665,7 +2753,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/eni.h Thu Jun 18 19:01:49 1998 ++++ work/drivers/atm/eni.h Tue Aug 4 17:54:42 1998 @@ -0,0 +1,114 @@ +/* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */ + @@ -3050,8 +3138,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/suni.c Tue Jun 9 21:32:11 1998 -@@ -0,0 +1,301 @@ ++++ work/drivers/atm/suni.c Fri Jul 24 23:49:36 1998 +@@ -0,0 +1,310 @@ +/* drivers/atm/suni.c - PMC SUNI (PHY) driver */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -3068,6 +3156,7 @@ +#include +#include +#include ++#include +#include +#include +#include @@ -3293,6 +3382,14 @@ + suni_hz(0); /* clear SUNI counters */ + (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ + cli(); ++{ ++int i; ++printk("SUNI:\n"); ++for (i = 0; i < 256; i++) { ++ printk(" %02x",dev->ops->phy_get(dev,i)); ++ if ((i & 15) == 15) printk("\n"); ++} ++} + if (!start_timer) restore_flags(flags); + else { + start_timer = 0; @@ -3354,11 +3451,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/suni.h Thu Jun 18 19:01:43 1998 -@@ -0,0 +1,219 @@ ++++ work/drivers/atm/suni.h Tue Aug 4 17:54:40 1998 +@@ -0,0 +1,210 @@ +/* drivers/atm/suni.h - PMC SUNI (PHY) declarations */ + -+/* Written 1995 by Werner Almesberger, EPFL LRC */ ++/* Written 1995,1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef DRIVER_ATM_SUNI_H @@ -3560,15 +3657,6 @@ + +#define SUNI_IDLE_PATTERN 0x6a /* idle pattern */ + -+/* ioctls */ -+ -+#define SUNI_GETLOOP _IOR('a',ATMIOC_PHYPRV,int) /* get loopback mode */ -+#define SUNI_SETLOOP _IO('a',ATMIOC_PHYPRV+1) /* set loopback mode */ -+ -+#define SUNI_LM_NONE 0 /* no loopback */ -+#define SUNI_LM_DIAG 1 /* diagnostic (i.e. loop TX to RX) */ -+#define SUNI_LM_LOOP 2 /* line (i.e. loop RX to TX) */ -+ + +#ifdef __KERNEL__ +int suni_init(struct atm_dev *dev); @@ -4230,8 +4318,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zatm.c Thu Jun 18 19:01:26 1998 -@@ -0,0 +1,1866 @@ ++++ work/drivers/atm/zatm.c Fri Jul 17 16:40:25 1998 +@@ -0,0 +1,1869 @@ +/* drivers/atm/zatm.c - ZeitNet ZN122x device driver */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -5085,7 +5173,8 @@ + dsc = (u32 *) kmalloc(uPD98401_TXPD_SIZE*2+ + uPD98401_TXBD_SIZE*skb->atm.iovcnt,GFP_ATOMIC); + if (!dsc) { -+ dev_kfree_skb(skb); ++ if (vcc->pop) vcc->pop(vcc,skb); ++ else dev_kfree_skb(skb); + return -EAGAIN; + } + /* @@@ should check alignment */ @@ -5977,12 +6066,14 @@ + + EVENT(">zatm_send 0x%lx\n",(unsigned long) skb,0); + if (!ZATM_VCC(vcc)->tx_chan || !(vcc->flags & ATM_VF_READY)) { -+ dev_kfree_skb(skb); ++ if (vcc->pop) vcc->pop(vcc,skb); ++ else dev_kfree_skb(skb); + return -EINVAL; + } + if (!skb) { + printk(KERN_CRIT "!skb in zatm_send ?\n"); -+ dev_kfree_skb(skb); ++ if (vcc->pop) vcc->pop(vcc,skb); ++ else dev_kfree_skb(skb); + return -EINVAL; + } + skb->atm.vcc = vcc; @@ -6099,7 +6190,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zatm.h Thu Jun 18 19:01:57 1998 ++++ work/drivers/atm/zatm.h Tue Aug 4 17:54:46 1998 @@ -0,0 +1,136 @@ +/* drivers/atm/zatm.h - ZeitNet ZN122x device driver declarations */ + @@ -6295,7 +6386,7 @@ #ifdef CONFIG_VT console_map_init(); --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/arequipa.h Tue Jun 9 21:50:44 1998 ++++ work/include/linux/arequipa.h Tue Aug 4 17:58:20 1998 @@ -0,0 +1,63 @@ +/* arequipa.h - Arequipa interface definitions */ + @@ -6361,8 +6452,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm.h Tue Jun 9 21:32:11 1998 -@@ -0,0 +1,235 @@ ++++ work/include/linux/atm.h Tue Aug 4 16:52:29 1998 +@@ -0,0 +1,234 @@ +/* atm.h - general ATM declarations */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -6582,7 +6673,6 @@ +}; + + -+#define SIOCSIFATMTCP _IO('a',ATMIOC_ITF) /* set ATMTCP mode */ +#define ATM_CREATE_LEAF _IO('a',ATMIOC_SPECIAL+2) + /* create a point-to-multipoint leaf socket */ + @@ -6617,8 +6707,30 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm_tcp.h Tue Jun 9 21:32:11 1998 -@@ -0,0 +1,30 @@ ++++ work/include/linux/atm_suni.h Fri Jul 17 16:47:52 1998 +@@ -0,0 +1,19 @@ ++/* atm_suni.h - Driver-specific declarations of the SUNI driver (for use by ++ driver-specific utilities) */ ++ ++/* Written 1998 by Werner Almesberger, EPFL ICA */ ++ ++ ++#ifndef LINUX_ATM_SUNI_H ++#define LINUX_ATM_SUNI_H ++ ++#include ++ ++#define SUNI_GETLOOP _IOR('a',ATMIOC_PHYPRV,int) /* get loopback mode */ ++#define SUNI_SETLOOP _IO('a',ATMIOC_PHYPRV+1) /* set loopback mode */ ++ ++#define SUNI_LM_NONE 0 /* no loopback */ ++#define SUNI_LM_DIAG 1 /* diagnostic (i.e. loop TX to RX) */ ++#define SUNI_LM_LOOP 2 /* line (i.e. loop RX to TX) */ ++ ++#endif +--- /dev/null Tue Jan 1 05:00:00 1980 ++++ work/include/linux/atm_tcp.h Tue Aug 4 17:53:34 1998 +@@ -0,0 +1,42 @@ +/* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by + driver-specific utilities) */ + @@ -6628,7 +6740,10 @@ +#ifndef LINUX_ATM_TCP_H +#define LINUX_ATM_TCP_H + ++#ifdef __KERNEL__ +#include ++#endif ++#include + + +/* @@ -6642,9 +6757,18 @@ +}; + + ++#define SIOCSIFATMTCP _IO('a',ATMIOC_ITF) /* set ATMTCP mode */ ++#define ATMTCP_CREATE _IO('a',ATMIOC_ITF+14) /* create persistent ATMTCP ++ interface */ ++#define ATMTCP_REMOVE _IO('a',ATMIOC_ITF+15) /* destroy persistent ATMTCP ++ interface*/ ++ ++ +#ifdef __KERNEL__ + +int atmtcp_attach(struct atm_vcc *vcc,int itf); ++int atmtcp_create_persistent(int itf); ++int atmtcp_remove_persistent(int itf); + +#endif + @@ -6752,11 +6876,11 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmclip.h Tue Jun 9 21:32:11 1998 -@@ -0,0 +1,21 @@ ++++ work/include/linux/atmclip.h Fri Jul 17 22:26:52 1998 +@@ -0,0 +1,26 @@ +/* atmclip.h - Classical IP over ATM */ + -+/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ ++/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ + + +#ifndef LINUX_ATMCLIP_H @@ -6774,10 +6898,15 @@ + +#define SIOCMKCLIP _IO('a',ATMIOC_CLIP) /* create IP interface */ + ++ ++#ifdef __KERNEL__ ++void clip_xmit_vcc(struct sk_buff *skb,struct atm_vcc *vcc); ++#endif ++ +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmdev.h Thu Jun 18 11:15:13 1998 -@@ -0,0 +1,304 @@ ++++ work/include/linux/atmdev.h Tue Aug 4 17:54:24 1998 +@@ -0,0 +1,309 @@ +/* atmdev.h - ATM device driver declarations */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -7063,7 +7192,10 @@ + +struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops, + int number,unsigned long flags); /* number == -1: pick first available */ ++struct atm_dev *atm_find_dev(int number); +void atm_dev_deregister(struct atm_dev *dev); ++void shutdown_atm_dev(struct atm_dev *dev); ++void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev); + + +/* This is the algorithm used by alloc_skb */ @@ -7079,6 +7211,8 @@ +int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci); +int atm_pcr_goal(struct atm_trafprm *tp); + ++void atm_async_release_vcc(struct atm_vcc *vcc,int reply); ++ +#endif /* __KERNEL__ */ + +#endif @@ -7124,7 +7258,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmlec.h Tue Jun 9 21:32:11 1998 ++++ work/include/linux/atmlec.h Tue Aug 4 17:58:20 1998 @@ -0,0 +1,65 @@ +/* + * @@ -7356,7 +7490,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmsvc.h Thu Jun 25 14:12:14 1998 ++++ work/include/linux/atmsvc.h Tue Aug 4 17:58:20 1998 @@ -0,0 +1,52 @@ +/* atmsvc.h - ATM signaling kernel-demon interface definitions */ + @@ -7411,7 +7545,7 @@ + +#endif --- ref/include/linux/if_arp.h Sun Jun 7 20:23:23 1998 -+++ work/include/linux/if_arp.h Tue Jun 9 21:45:55 1998 ++++ work/include/linux/if_arp.h Tue Jul 28 21:35:51 1998 @@ -35,6 +35,7 @@ #define ARPHRD_ARCNET 7 /* ARCnet */ #define ARPHRD_APPLETLK 8 /* APPLEtalk */ @@ -7509,7 +7643,7 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/net/atmclip.h Thu Jun 18 19:02:24 1998 ++++ work/include/net/atmclip.h Tue Aug 4 17:58:12 1998 @@ -0,0 +1,62 @@ +/* net/atm/atmarp.h - RFC1577 ATM ARP */ + @@ -7672,6 +7806,578 @@ return (dst->neighbour != NULL); } +--- ref/net/sched/Config.in Thu May 14 19:26:23 1998 ++++ work/net/sched/Config.in Fri Jul 24 17:33:35 1998 +@@ -7,6 +7,9 @@ + tristate 'CSZ packet scheduler' CONFIG_NET_SCH_CSZ + #tristate 'H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ + #tristate 'H-FSC packet scheduler' CONFIG_NET_SCH_HFCS ++if [ "$CONFIG_ATM" = "y" ]; then ++ bool 'ATM pseudo-scheduler' CONFIG_NET_SCH_ATM ++fi + tristate 'The simplest PRIO pseudoscheduler' CONFIG_NET_SCH_PRIO + tristate 'RED queue' CONFIG_NET_SCH_RED + tristate 'SFQ queue' CONFIG_NET_SCH_SFQ +--- ref/net/sched/Makefile Tue Apr 28 20:10:11 1998 ++++ work/net/sched/Makefile Fri Jul 24 02:13:11 1998 +@@ -7,6 +7,8 @@ + # + # Note 2! The CFLAGS definition is now in the main makefile... + ++CFLAGS += -g # while hacking ATM ... ++ + O_TARGET := sched.o + + O_OBJS := sch_generic.o +@@ -99,6 +101,10 @@ + ifeq ($(CONFIG_NET_SCH_TEQL), m) + M_OBJS += sch_teql.o + endif ++endif ++ ++ifeq ($(CONFIG_NET_SCH_ATM), y) ++O_OBJS += sch_atm.o + endif + + ifeq ($(CONFIG_NET_CLS_U32), y) +--- ref/net/sched/sch_api.c Fri May 8 09:08:02 1998 ++++ work/net/sched/sch_api.c Fri Jul 24 01:08:38 1998 +@@ -981,6 +981,9 @@ + #ifdef CONFIG_NET_SCH_PRIO + INIT_QDISC(prio); + #endif ++#ifdef CONFIG_NET_SCH_ATM ++ INIT_QDISC(atm); ++#endif + #ifdef CONFIG_NET_CLS + tc_filter_init(); + #endif +--- /dev/null Tue Jan 1 05:00:00 1980 ++++ work/net/sched/sch_atm.c Tue Aug 4 22:00:38 1998 +@@ -0,0 +1,523 @@ ++/* net/sched/sch_atm.c - ATM VC selection "queueing discipline" */ ++ ++/* Written 1998 by Werner Almesberger, EPFL ICA */ ++ ++ ++/* ++ * NOTE: There are still essential parts (e.g. policing) missing. So don't ++ * depend too much on the existing interfaces ... ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* for fput */ ++#include ++#include ++ ++ ++extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ ++#define sockfd_put(sock) fput((sock)->file) ++ ++ ++#if 1 /* control */ ++#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) ++#else ++#define DPRINTK(format,args...) ++#endif ++ ++#if 0 /* data */ ++#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args) ++#else ++#define D2PRINTK(format,args...) ++#endif ++ ++ ++/* ++ * The ATM queuing discipline provides a framework for invoking classifiers ++ * (aka "filters"), which in turn select classes of this queuing discipline. ++ * Each class maps the flow(s) it is handling to a given VC. More than one ++ * class may use the same VC. ++ * ++ * When creating a class, VCs are specified by passing the number of the open ++ * socket descriptor by which the calling process references the VC. The kernel ++ * keeps the VC open at least until all classes using it are removed. ++ * ++ * In this file, most functions are named atm_tc_* to avoid confusion with all ++ * the atm_* in net/atm. This naming convention differs from what's used in the ++ * rest of net/sched. ++ * ++ * Known bugs: ++ * - sometimes messes up the IP stack ++ * - no policing yet ++ * - may panic if there's not enough space in an skb to add the CLIP header ++ * - any manipulations besides the few operations described in the README, are ++ * untested and likely to crash the system ++ * - takes a few dirty shortcuts on rtnetlink ++ */ ++ ++ ++#define PRIV(sch) ((struct atm_qdisc_data *) (sch)->data) ++ ++ ++struct atm_flow_data { ++ struct Qdisc *q; /* FIFO, TBF, etc. */ ++ struct tcf_proto *filter_list; ++ struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */ ++ struct socket *sock; /* for closing */ ++ unsigned long classid; /* x:y type ID */ ++ int ref; /* reference count */ ++ struct tc_stats stats; ++ struct atm_flow_data *next; ++}; ++ ++struct atm_qdisc_data { ++ struct atm_flow_data link; /* unclassified skbs go here */ ++ struct atm_flow_data *flows; /* NB: "link" is also on this ++ list */ ++}; ++ ++ ++/* ------------------------- Class/flow operations ------------------------- */ ++ ++ ++static int find_flow(struct atm_qdisc_data *qdisc,struct atm_flow_data *flow) ++{ ++ struct atm_flow_data *walk; ++ ++ DPRINTK("find_flow(qdisc %p,flow %p)\n",qdisc,flow); ++ for (walk = qdisc->flows; walk; walk = walk->next) ++ if (walk == flow) return 1; ++ DPRINTK("find_flow: not found\n"); ++ return 0; ++} ++ ++ ++static int atm_tc_graft(struct Qdisc *sch,unsigned long arg, ++ struct Qdisc *new,struct Qdisc **old) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow = (struct atm_flow_data *) arg; ++ ++ DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",sch, ++ p,flow,new,old); ++ if (!find_flow(p,flow)) return -EINVAL; ++ if (!new) new = &noop_qdisc; ++ *old = xchg(&flow->q,new); ++ return 0; ++} ++ ++ ++static unsigned long atm_tc_get(struct Qdisc *sch,u32 classid) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow; ++ ++ DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %p)\n",sch,p, ++ (void *) classid); ++ for (flow = PRIV(sch)->flows; flow; flow = flow->next) ++ if (flow->classid == classid) break; ++ if (flow) flow->ref++; ++ DPRINTK("atm_tc_get: flow %p\n",flow); ++ return (unsigned long) flow; ++} ++ ++ ++/* ++ * atm_tc_put handles all destructions, including the ones that are explicitly ++ * requested (atm_tc_destroy, etc.). The assumption here is that we never drop ++ * anything that still seems to be in use. ++ */ ++ ++static void atm_tc_put(struct Qdisc *sch, unsigned long cl) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow = (struct atm_flow_data *) cl; ++ struct atm_flow_data **prev; ++ struct tcf_proto *filter; ++ ++ DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); ++ if (--flow->ref) return; ++ DPRINTK("atm_tc_put: destroying\n"); ++ for (prev = &p->flows; *prev; prev = &(*prev)->next) ++ if (*prev == flow) break; ++ if (!*prev) { ++ printk(KERN_ERR "atm_tc_put: class %p not found\n",flow); ++ return; ++ } ++ *prev = flow->next; ++ DPRINTK("atm_tc_put: qdisc %p\n",flow->q); ++ qdisc_destroy(flow->q); ++ while ((filter = flow->filter_list)) { ++ DPRINTK("atm_tc_put: destroying filter %p\n",filter); ++ flow->filter_list = filter->next; ++ DPRINTK("atm_tc_put: filter %p\n",filter); ++ filter->ops->destroy(filter); ++ } ++ if (flow->sock) { ++ DPRINTK("atm_tc_put: f_count %d\n",flow->sock->file->f_count); ++ sockfd_put(flow->sock); ++ } ++ if (flow != &p->link) kfree(flow); ++ /* ++ * If flow == &p->link, the qdisc no longer works at this point and ++ * needs to be removed. (By the caller of atm_tc_put.) ++ */ ++} ++ ++ ++static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, ++ struct rtattr **tca, unsigned long *arg) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow = (struct atm_flow_data *) *arg; ++ struct rtattr *opt = tca[TCA_OPTIONS-1]; ++ struct socket *sock; ++ int fd,error; ++ ++ DPRINTK("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x," ++ "flow %p,opt %p)\n",sch,p,classid,parent,flow,opt); ++ /* ++ * The concept of parents doesn't apply for this qdisc. ++ */ ++ if (parent && parent != TC_H_ROOT) return -EINVAL; ++ /* ++ * ATM classes cannot be changed. In order to change properties of the ++ * ATM connection, that socket needs to be modified directly (via the ++ * native ATM API. In order to send a flow to a different VC, the old ++ * class needs to be removed and a new one added. ++ */ ++ if (flow) return -EBUSY; ++ /* ++ * @@@ Just treat the whole option block as our argument. (Technically, ++ * this makes sense, because there's only one variable and it's ++ * required anyway. Of course, this differs from how things are done ++ * elsewhere. Need to fix it when adding policing ...) ++ */ ++ DPRINTK("atm_tc_change: type %d, payload %d\n",opt->rta_type, ++ RTA_PAYLOAD(opt)); ++ if (RTA_PAYLOAD(*tca) != sizeof(int)) return -EINVAL; ++ fd = *(int *) RTA_DATA(opt); ++ DPRINTK("atm_tc_change: fd %d\n",fd); ++ if (!(sock = sockfd_lookup(fd,&error))) return error; /* f_count++ */ ++ DPRINTK("atm_tc_change: f_count %d\n",sock->file->f_count); ++ if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) { ++ error = -EPROTOTYPE; ++ goto err_out; ++ } ++ /* @@@ should check if the socket is really operational or we'll crash ++ on vcc->dev->ops->send */ ++ if (classid) { ++ if (TC_H_MAJ(classid ^ sch->handle)) { ++ DPRINTK("atm_tc_change: classid mismatch\n"); ++ error = -EINVAL; ++ goto err_out; ++ } ++ if (find_flow(p,flow)) { ++ error = -EEXIST; ++ goto err_out; ++ } ++ } ++ else { ++ int i; ++ unsigned long cl; ++ ++ for (i = 1; i < 0x8000; i++) { ++ classid = TC_H_MAKE(sch->handle,0x8000 | i); ++ if (!(cl = atm_tc_get(sch,classid))) break; ++ atm_tc_put(sch,cl); ++ } ++ } ++ DPRINTK("atm_tc_change: new id %x\n",classid); ++ flow = kmalloc(sizeof(struct atm_flow_data),GFP_KERNEL); ++ DPRINTK("atm_tc_change: flow %p\n",flow); ++ if (!flow) { ++ error = -ENOBUFS; ++ goto err_out; ++ } ++ memset(flow,0,sizeof(*flow)); ++ flow->filter_list = NULL; ++ if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops))) ++ flow->q = &noop_qdisc; ++ DPRINTK("atm_tc_change: qdisc %p\n",flow->q); ++ flow->sock = sock; ++ flow->vcc = ATM_SD(sock); /* speedup */ ++ DPRINTK("atm_tc_change: vcc %p\n",flow->vcc); ++ flow->classid = classid; ++ flow->ref = 1; ++ flow->next = p->link.next; ++ p->link.next = flow; ++ *arg = (unsigned long) flow; ++ return 0; ++err_out: ++ sockfd_put(sock); ++ return error; ++} ++ ++ ++static int atm_tc_delete(struct Qdisc *sch,unsigned long arg) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow = (struct atm_flow_data *) arg; ++ ++ DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); ++ if (!find_flow(PRIV(sch),flow)) return -EINVAL; ++ if (flow->filter_list || flow == &p->link) return -EBUSY; ++ atm_tc_put(sch,arg); ++ return 0; ++} ++ ++ ++static void atm_tc_walk(struct Qdisc *sch,struct qdisc_walker *walker) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow; ++ ++ DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker); ++ if (walker->stop) return; ++ for (flow = p->flows; flow; flow = flow->next) { ++ if (walker->count >= walker->skip) ++ if (walker->fn(sch,(unsigned long) flow,walker) < 0) { ++ walker->stop = 1; ++ break; ++ } ++ walker->count++; ++ } ++} ++ ++ ++static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch,unsigned long cl) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow = (struct atm_flow_data *) cl; ++ ++ DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); ++ return flow ? &flow->filter_list : &p->link.filter_list; ++} ++ ++ ++/* --------------------------- Qdisc operations ---------------------------- */ ++ ++ ++static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow; ++ struct tcf_result res; ++ ++ D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p); ++ for (flow = p->link.next; flow; flow = flow->next) ++ if (flow->filter_list && tc_classify(skb,flow->filter_list, ++ &res) >= 0) break; ++ if (!flow) flow = &p->link; ++ if (flow->q->enqueue(skb,flow->q) != 1) { ++ sch->stats.drops++; ++ if (flow) flow->stats.drops++; ++ return 0; ++ } ++ sch->stats.bytes += skb->len; ++ sch->stats.packets++; ++ flow->stats.bytes += skb->len; ++ flow->stats.packets++; ++ sch->q.qlen++; ++ return 1; ++} ++ ++ ++static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow; ++ struct sk_buff *skb; ++ ++ D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n",sch,p); ++ for (flow = p->link.next; flow; flow = flow->next) ++ /* ++ * If traffic is properly shaped, this won't generate nasty ++ * little bursts. Otherwise, it may ... @@@ ++ */ ++ while (skb = flow->q->dequeue(flow->q)) { ++ sch->q.qlen--; ++ D2PRINTK("atm_tc_deqeueue: sending on class %p\n",flow); ++ /* ++ * Now we're in the unfortunate situation that the ++ * packet header may have to change. So we remove all ++ * other headers first. Then clip_xmit_vcc will try to ++ * add the RFC1483 header. If we're unlucky, we panic, ++ * because there's not enough space left ... ++ * ++ * To avoid this, we should call skb_realloc_headroom ++ * when we detect that there's not enough space. @@@ ++ */ ++ D2PRINTK("atm_tc_dequeue: ip %p, data %p\n", ++ skb->nh.iph,skb->data); ++ skb_pull(skb,(char *) skb->nh.iph-(char *) skb->data); ++ clip_xmit_vcc(skb,flow->vcc); ++ } ++ skb = p->link.q->dequeue(p->link.q); ++ if (skb) sch->q.qlen--; ++ return skb; ++} ++ ++ ++static int atm_tc_drop(struct Qdisc *sch) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow; ++ ++ DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n",sch,p); ++ for (flow = p->flows; flow; flow = flow->next) ++ if (flow->q->ops->drop && flow->q->ops->drop(flow->q)) ++ return 1; ++ return 0; ++} ++ ++ ++static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ ++ DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); ++ memset(p,0,sizeof(*p)); ++ p->flows = &p->link; ++ if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops))) ++ p->link.q = &noop_qdisc; ++ DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q); ++ p->link.filter_list = NULL; ++ p->link.vcc = NULL; ++ p->link.sock = NULL; ++ p->link.classid = sch->handle; ++ p->link.ref = 1; ++ p->link.next = NULL; ++ MOD_INC_USE_COUNT; ++ return 0; ++} ++ ++ ++static void atm_tc_reset(struct Qdisc *sch) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow; ++ ++ DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n",sch,p); ++ for (flow = p->flows; flow; flow = flow->next) qdisc_reset(flow->q); ++ sch->q.qlen = 0; ++} ++ ++ ++static void atm_tc_destroy(struct Qdisc *sch) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow; ++ ++ DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p); ++ /* races ? */ ++ while ((flow = p->flows)) { ++ struct tcf_proto *filter; ++ ++ for (filter = flow->filter_list; filter; filter = filter->next) ++ filter->ops->destroy(filter); ++ if (flow->ref > 1) ++ printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow, ++ flow->ref); ++ atm_tc_put(sch,(unsigned long) flow); ++ if (p->flows == flow) { ++ printk(KERN_ERR "atm_destroy: putting flow %p didn't " ++ "kill it\n",flow); ++ p->flows = flow->next; /* brute force */ ++ break; ++ } ++ } ++ MOD_DEC_USE_COUNT; ++} ++ ++ ++#ifdef CONFIG_RTNETLINK ++ ++static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, ++ struct sk_buff *skb, struct tcmsg *tcm) ++{ ++ struct atm_qdisc_data *p = PRIV(sch); ++ struct atm_flow_data *flow = (struct atm_flow_data *) cl; ++ ++ DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", ++ sch,p,flow,skb,tcm); ++ if (!find_flow(p,flow)) return -EINVAL; ++ if (flow->vcc) { ++ struct sockaddr_atmpvc pvc; ++ ++ pvc.sap_family = AF_ATMPVC; ++ pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1; ++ pvc.sap_addr.vpi = flow->vcc->vpi; ++ pvc.sap_addr.vci = flow->vcc->vci; ++ RTA_PUT(skb,TCA_OPTIONS,sizeof(pvc),&pvc); ++ } ++ return skb->len; ++rtattr_failure: ++ return -1; ++} ++ ++static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb) ++{ ++ return 0; ++} ++ ++#endif ++ ++ ++static struct Qdisc_class_ops atm_class_ops = ++{ ++ atm_tc_graft, /* graft */ ++ atm_tc_get, /* get */ ++ atm_tc_put, /* put */ ++ atm_tc_change, /* change */ ++ atm_tc_delete, /* delete */ ++ atm_tc_walk, /* walk */ ++ ++ atm_tc_find_tcf, /* tcf_chain */ ++ atm_tc_get, /* bind_tcf */ ++ atm_tc_put, /* unbind_tcf */ ++ ++#ifdef CONFIG_RTNETLINK ++ atm_tc_dump_class, /* dump */ ++#endif ++}; ++ ++struct Qdisc_ops atm_qdisc_ops = ++{ ++ NULL, /* next */ ++ &atm_class_ops, /* cl_ops */ ++ "atm", ++ sizeof(struct atm_qdisc_data), ++ ++ atm_tc_enqueue, /* enqueue */ ++ atm_tc_dequeue, /* dequeue */ ++ atm_tc_enqueue, /* requeue */ ++ atm_tc_drop, /* drop */ ++ ++ atm_tc_init, /* init */ ++ atm_tc_reset, /* reset */ ++ atm_tc_destroy, /* destroy */ ++ ++#ifdef CONFIG_RTNETLINK ++ atm_tc_dump /* dump */ ++#endif ++}; ++ ++ ++#ifdef MODULE ++int init_module(void) ++{ ++ return register_qdisc(&atm_qdisc_ops); ++} ++ ++ ++void cleanup_module(void) ++{ ++ unregister_qdisc(&atm_qdisc_ops); ++} ++#endif --- /dev/null Tue Jan 1 05:00:00 1980 +++ work/net/atm/Makefile Tue Jun 9 21:32:12 1998 @@ -0,0 +1,52 @@ @@ -7890,7 +8596,7 @@ + return total; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/addr.h Thu Jun 18 19:02:34 1998 ++++ work/net/atm/addr.h Tue Aug 4 17:58:20 1998 @@ -0,0 +1,18 @@ +/* net/atm/addr.h - Local ATM address registry */ + @@ -7911,8 +8617,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/clip.c Wed Jun 17 02:54:35 1998 -@@ -0,0 +1,645 @@ ++++ work/net/atm/clip.c Fri Jul 24 03:28:37 1998 +@@ -0,0 +1,664 @@ +/* clip.c - RFC1577 Classical IP over ATM */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -8040,10 +8746,9 @@ + struct clip_vcc *clip_vcc; + + for (clip_vcc = entry->vccs; clip_vcc; -+ clip_vcc = clip_vcc->next) { -+ if (clip_vcc->vcc->family == PF_ATMPVC) -+ continue; -+ if (clip_vcc->last_use+clip_vcc->idle_timeout < ++ clip_vcc = clip_vcc->next) ++ if (clip_vcc->idle_timeout && ++ clip_vcc->last_use+clip_vcc->idle_timeout < + jiffies) { + DPRINTK("releasing vcc %p->%p of " + "entry %p\n",clip_vcc,clip_vcc->vcc, @@ -8051,7 +8756,6 @@ + atm_async_release_vcc(clip_vcc->vcc, + -ETIMEDOUT); + } -+ } + if (entry->vccs || entry->expires > jiffies) { + np = &n->next; + continue; @@ -8101,7 +8805,7 @@ + DPRINTK("clip push\n"); + if (!skb) { + DPRINTK("removing VCC %p\n",clip_vcc); -+ unlink_clip_vcc(clip_vcc); ++ if (clip_vcc->entry) unlink_clip_vcc(clip_vcc); + clip_vcc->old_push(vcc,NULL); /* pass on the bad news */ + kfree(clip_vcc); + return; @@ -8239,6 +8943,25 @@ +} + + ++/* ++ * For playing with RSVP. Should later be merged with clip_start_xmit ++ */ ++ ++ ++void clip_xmit_vcc(struct sk_buff *skb,struct atm_vcc *vcc) ++{ ++ void *here; ++ ++ skb->atm.vcc = vcc; ++ here = skb_push(skb,RFC1483LLC_LEN); ++ memcpy(here,llc_oui,sizeof(llc_oui)); ++ ((u16 *) here)[3] = skb->protocol; ++ atomic_add(skb->truesize,&vcc->tx_inuse); ++ skb->atm.iovcnt = 0; ++ (void) vcc->dev->ops->send(vcc,skb); ++} ++ ++ +static int clip_start_xmit(struct sk_buff *skb,struct device *dev) +{ + struct atmarp_entry *entry; @@ -8291,7 +9014,7 @@ + entry->vccs->last_use = jiffies; + DPRINTK("skb(%p)->atm.vcc(%p)->dev(%p)\n",skb,skb->atm.vcc, + skb->atm.vcc->dev); -+ skb->atm.vcc->dev->ops->send(skb->atm.vcc,skb); ++ (void) skb->atm.vcc->dev->ops->send(skb->atm.vcc,skb); + PRIV(dev)->stats.tx_packets++; + return 0; +} @@ -8325,11 +9048,13 @@ + cli(); + vcc->push = clip_push; + skb_migrate(&vcc->recvq,©); -+ atomic_set(&vcc->rx_inuse,0); + restore_flags(flags); + /* re-process everything received between connection setup and MKIP */ + while ((skb = skb_dequeue(©))) -+ if (!clip_devs) kfree_skb(skb); ++ if (!clip_devs) { ++ atm_return(vcc,skb->truesize); ++ kfree_skb(skb); ++ } + else { + clip_push(vcc,skb); + PRIV(skb->dev)->stats.rx_packets--; @@ -8559,8 +9284,8 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/common.c Tue Jun 9 21:32:12 1998 -@@ -0,0 +1,903 @@ ++++ work/net/atm/common.c Tue Aug 4 18:15:09 1998 +@@ -0,0 +1,909 @@ +/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -9232,6 +9957,12 @@ + error = atmtcp_attach(vcc,(int) arg); + if (error >= 0) sock->state = SS_CONNECTED; + return error; ++ case ATMTCP_CREATE: ++ if (!suser()) return -EPERM; ++ return atmtcp_create_persistent((int) arg); ++ case ATMTCP_REMOVE: ++ if (!suser()) return -EPERM; ++ return atmtcp_remove_persistent((int) arg); +#endif + default: + break; @@ -9465,8 +10196,8 @@ + return atm_do_getsockopt(sock,level,optname,optval,len); +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/common.h Tue Jun 9 21:50:44 1998 -@@ -0,0 +1,44 @@ ++++ work/net/atm/common.h Fri Jul 17 22:28:30 1998 +@@ -0,0 +1,46 @@ +/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -9496,7 +10227,9 @@ +int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci); +int atm_release_vcc(struct atm_vcc *vcc,int free_vcc); +int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos); ++/* -- now in atmdev.h: +void atm_async_release_vcc(struct atm_vcc *vcc,int reply); ++*/ +void atm_shutdown_dev(struct atm_dev *dev); + +int atm_proc_init(void); @@ -9567,7 +10300,7 @@ + skb_queue_head_init(from); +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/ipcommon.h Thu Jun 18 19:02:55 1998 ++++ work/net/atm/ipcommon.h Tue Aug 4 17:58:35 1998 @@ -0,0 +1,22 @@ +/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */ + @@ -9777,8 +10510,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec.c Wed Jun 24 19:01:47 1998 -@@ -0,0 +1,1895 @@ ++++ work/net/atm/lec.c Tue Aug 4 20:41:09 1998 +@@ -0,0 +1,1896 @@ +/* + * lec.c: Lan Emulation driver + * Marko Kiiskila carnil@cs.tut.fi @@ -9811,6 +10544,7 @@ +#include "lec.h" +#include "lec_arpc.h" +#include "tunable.h" ++#include "resources.h" + + +#define DPRINTK(format,args...) @@ -11675,7 +12409,7 @@ +} + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec.h Thu Jun 18 19:02:33 1998 ++++ work/net/atm/lec.h Tue Aug 4 17:58:20 1998 @@ -0,0 +1,112 @@ +/* + * @@ -11790,7 +12524,7 @@ +#endif _LEC_H_ + --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec_arpc.h Thu Jun 18 19:02:34 1998 ++++ work/net/atm/lec_arpc.h Tue Aug 4 17:58:20 1998 @@ -0,0 +1,112 @@ +/* + * Lec arp cache @@ -12777,8 +13511,8 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/resources.c Tue Jun 9 21:32:12 1998 -@@ -0,0 +1,183 @@ ++++ work/net/atm/resources.c Tue Aug 4 16:47:00 1998 +@@ -0,0 +1,186 @@ +/* net/atm/resources.c - Staticly allocated resources */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC */ @@ -12894,10 +13628,6 @@ +} + + -+EXPORT_SYMBOL(atm_dev_register); -+EXPORT_SYMBOL(atm_dev_deregister); -+ -+ +void shutdown_atm_dev(struct atm_dev *dev) +{ + if (dev->vccs) { @@ -12962,9 +13692,16 @@ + nodev_vccs = vcc; + } +} ++ ++ ++EXPORT_SYMBOL(atm_dev_register); ++EXPORT_SYMBOL(atm_dev_deregister); ++EXPORT_SYMBOL(atm_find_dev); ++EXPORT_SYMBOL(shutdown_atm_dev); ++EXPORT_SYMBOL(bind_vcc); --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/resources.h Thu Jun 18 19:02:34 1998 -@@ -0,0 +1,29 @@ ++++ work/net/atm/resources.h Tue Aug 4 17:54:33 1998 +@@ -0,0 +1,25 @@ +/* net/atm/resources.h - ATM-related resources */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -12981,12 +13718,8 @@ +extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */ + + -+struct atm_dev *atm_find_dev(int number); -+void shutdown_atm_dev(struct atm_dev *dev); -+ +struct atm_vcc *alloc_atm_vcc(void); +void free_atm_vcc(struct atm_vcc *vcc); -+void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev); + +#ifdef CONFIG_PROC_FS +int atm_proc_dev_register(struct atm_dev *dev); @@ -12995,8 +13728,8 @@ + +#endif --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/signaling.c Wed Jun 24 18:58:25 1998 -@@ -0,0 +1,253 @@ ++++ work/net/atm/signaling.c Tue Aug 4 18:41:24 1998 +@@ -0,0 +1,252 @@ +/* net/atm/signaling.c - ATM signaling */ + +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ @@ -13120,8 +13853,7 @@ + vcc = (struct atm_vcc *) msg->listen_vcc; + DPRINTK("as_indicate!!!\n"); + if (!vcc->backlog_quota) { -+ sigd_enq(0,as_reject,(struct atm_vcc *) -+ msg->listen_vcc,NULL,NULL); ++ sigd_enq(0,as_reject,vcc,NULL,NULL); + return 0; + } + vcc->backlog_quota--; @@ -13251,7 +13983,7 @@ + return 0; +} --- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/signaling.h Thu Jun 18 19:02:34 1998 ++++ work/net/atm/signaling.h Tue Aug 4 17:58:20 1998 @@ -0,0 +1,25 @@ +/* net/atm/signaling.h - ATM signaling */ + diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex --- old/atm/doc/usage.tex Thu Jun 25 13:29:22 1998 +++ new/atm/doc/usage.tex Tue Aug 4 19:18:10 1998 @@ -1,7 +1,7 @@ %%def%:= %:\begin{verbatim} -%:Usage instructions - ATM on Linux, release 0.38 +%:Usage instructions - ATM on Linux, release 0.39 %:------------------------------------------------- %: %:\end{verbatim} @@ -38,14 +38,14 @@ \title{ATM on Linux \\ User's guide \\ - Release 0.38 (alpha)} + Release 0.39 (alpha)} \author{Werner Almesberger \\ {\tt Werner.Almesberger@epfl.ch} \\ \\ Institute for computer Communications and Applications (ICA) \\ EPFL, CH-1015 Lausanne, Switzerland} -\date{June 25, 1998} +\date{August 4, 1998} \begin{document} \maketitle @@ -81,7 +81,7 @@ In order to install this package, you need \begin{itemize} \item the package itself - \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.38.tar.gz} + \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.39.tar.gz} \item the Linux kernel, version 2.1.105, e.g. from \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.105.tar.gz} \item Perl, version 4 or 5 @@ -98,7 +98,7 @@ distribution: \begin{verbatim} -tar xfz atm-0.38.tar.gz +tar xfz atm-0.39.tar.gz \end{verbatim} and the kernel source: @@ -195,13 +195,6 @@ \subsection{Driver messages} -If you've configured the ATM over TCP driver, you should see eight lines -like this one: - -\begin{verbatim} -atmtcp(itf 1): ready -\end{verbatim} - If you've configured the ENI155p-MF driver, you should see two lines like these: {\footnotesize @@ -220,6 +213,10 @@ \end{verbatim}} Note that your board needs to be at least at revision level 3 if you want to use it in a Triton-based system. + +Note that if you've configured only the ATM over TCP driver, there are no +messages at startup, because ATM over TCP devices are created later using +the \name{atmtcp} command. \subsection{Memory debugging} diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt --- old/atm/doc/usage.txt Thu Jun 25 14:13:40 1998 +++ new/atm/doc/usage.txt Tue Aug 4 21:15:42 1998 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.38 +Usage instructions - ATM on Linux, release 0.39 ------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -17,7 +17,7 @@ In order to install this package, you need - the package itself - ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.38.tar.gz + ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.39.tar.gz - the Linux kernel, version 2.1.105, e.g. from ftp://ftp.kernel.org/pub/linux/kernel/v2.1/linux-2.1.105.tar.gz - Perl, version 4 or 5 @@ -33,7 +33,7 @@ all the files listed above there. Then extract the ATM on Linux distribution: -tar xfz atm-0.38.tar.gz +tar xfz atm-0.39.tar.gz and the kernel source: @@ -97,11 +97,6 @@ Driver messages --------------- -If you've configured the ATM over TCP driver, you should see eight lines -like this one: - -atmtcp(itf 1): ready - If you've configured the ENI155p-MF driver, you should see two lines like these: @@ -118,6 +113,10 @@ Note that your board needs to be at least at revision level 3 if you want to use it in a Triton-based system. + +Note that if you've configured only the ATM over TCP driver, there are no +messages at startup, because ATM over TCP devices are created later using +the atmtcp command. Memory debugging diff -ur --new-file old/atm/extra/tc/Makefile.patch new/atm/extra/tc/Makefile.patch --- old/atm/extra/tc/Makefile.patch Thu Jan 1 01:00:00 1970 +++ new/atm/extra/tc/Makefile.patch Thu Jul 23 23:42:43 1998 @@ -0,0 +1,19 @@ +--- iproute2/tc/Makefile Sat May 9 18:46:58 1998 ++++ wa/tc/Makefile Thu Jul 23 22:00:10 1998 +@@ -7,6 +7,7 @@ + TCMODULES += q_prio.o + TCMODULES += q_tbf.o + TCMODULES += q_cbq.o ++TCMODULES += q_atm.o + TCMODULES += f_rsvp.o + TCMODULES += f_u32.o + #TCMODULES += q_csz.o +@@ -20,7 +21,7 @@ + TCLIB += tc_cbq.o + TCLIB += tc_estimator.o + +-LDLIBS += -L. -ltc -lm -ldl ++LDLIBS += -L. -ltc -lm -ldl -latm + LDFLAGS += -Wl,-export-dynamic + + all: libtc.a tc diff -ur --new-file old/atm/extra/tc/README new/atm/extra/tc/README --- old/atm/extra/tc/README Thu Jan 1 01:00:00 1970 +++ new/atm/extra/tc/README Fri Jul 24 01:20:05 1998 @@ -0,0 +1,65 @@ +1. When configuring the kernel, select at least the following options under + "Networking options": + - kernel/User netlink socket + - QoS and/or fair queueing + - ATM pseudoscheduler + - Packet classifier API + - Routing tables based classifier + You may select additional schedulers/classifiers/etc. As usual, module + support is not tested yet, so you should select "y", not "m". + +2. Build the kernel. + +3. Download iproute2-2.1.99-now-ss980630.tar.gz either from + ftp://ftp.inr.ac.ru/ip-routing/ or one of its mirrors, or from + ftp://lrcftp.epfl.ch/pub/people/almesber/misc/ + +4. Add the ATM queuing discipline to "tc" (assuming that we're in + atm/extra/tc): + - tar xvfz iproute2-2.1.99-now-ss980630.tar.gz + - cd iproute2/tc + - patch -s -p2 <../../Makefile.patch + - cp ../../q_atm.c . + +5. Build tc: + - cd .. + - make + - cd tc + +6. Run a little example. We first set up the ATM queuing discipline to + intercept selected traffic through our Ethernet interface "eth0" and + to forward this traffic over a PVC 0.100: + + # ./tc qdisc add dev eth0 handle 1: root atm + # ./tc class add dev eth0 classid 1:1 atm pvc 0.100 + + Verify that the operation succeeded: + + % ./tc qdisc show dev eth0 + qdisc atm 1: root + % ./tc class show dev eth0 + class atm 1: parent 1: + class atm 1: parent 1: 0.0.100 + + (The first class is used to send all traffic that isn't explicitly + selected for ATM over the normal Ethernet interface. This class is + automatically created when setting up the ATM queuing discipline.) + + Next, we add a filter and set up a route that selects it. If you + have enabled other filters, you can also try to select flows via + firewall rules, etc. + + # ./tc filter add dev eth0 parent 1:1 protocol ip route + # ../ip/ip route add 10.0.0.0/8 dev eth0 flow 0x10001 + + Test the redirection to ATM: + + % ping 10.0.0.1 + + Remove the ATM queuing discipline again: + + # ./tc qdisc del dev eth0 root + + Verify that the PVC has been removed: + + % cat /proc/atm/pvc diff -ur --new-file old/atm/extra/tc/q_atm.c new/atm/extra/tc/q_atm.c --- old/atm/extra/tc/q_atm.c Thu Jan 1 01:00:00 1970 +++ new/atm/extra/tc/q_atm.c Thu Jul 23 23:14:49 1998 @@ -0,0 +1,145 @@ +/* + * q_atm.c ATM. + * + * Hacked 1998 by Werner Almesberger, EPFL ICA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "tc_util.h" + + +#define usage() return(-1) + +static int atm_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +{ + if (argc) { + fprintf(stderr,"Usage: atm\n"); + return -1; + } + return 0; +} + + +static void explain(void) +{ + fprintf(stderr, "Usage: ... atm ( pvc ADDR | svc ADDR [ sap SAP ] ) " + "[ qos QOS ]\n"); +} + + +static int atm_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n) +{ + struct sockaddr_atmsvc addr; + struct atm_qos qos; + struct atm_sap sap; + int s; + + memset(&addr,0,sizeof(addr)); + (void) text2qos("aal5,ubr:sdu=9180,rx:none",&qos,0); + (void) text2sap("blli:l2=iso8802",&sap,0); + while (argc > 0) { + if (!strcmp(*argv,"pvc")) { + NEXT_ARG(); + if (text2atm(*argv,(struct sockaddr *) &addr, + sizeof(addr),T2A_PVC | T2A_NAME) < 0) { + explain(); + return -1; + } + } + else if (!strcmp(*argv,"svc")) { + NEXT_ARG(); + if (text2atm(*argv,(struct sockaddr *) &addr, + sizeof(addr),T2A_SVC | T2A_NAME) < 0) { + explain(); + return -1; + } + } + else if (!strcmp(*argv,"qos")) { + NEXT_ARG(); + if (text2qos(*argv,&qos,0) < 0) { + explain(); + return -1; + } + } + else if (!strcmp(*argv,"sap")) { + NEXT_ARG(); + if (addr.sas_family != AF_ATMSVC || + text2sap(*argv,&sap,T2A_NAME) < 0) { + explain(); + return -1; + } + } + else { + explain(); + return 1; + } + argc--; + argv++; + } + s = socket(addr.sas_family,SOCK_DGRAM,0); + if (s < 0) { + perror("socket"); + return -1; + } + if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { + perror("SO_ATMQOS"); + return -1; + } + if (addr.sas_family == AF_ATMSVC && setsockopt(s,SOL_ATM,SO_ATMSAP, + &sap,sizeof(sap)) < 0) { + perror("SO_ATMSAP"); + return -1; + } + if (connect(s,(struct sockaddr *) &addr,addr.sas_family == AF_ATMPVC ? + sizeof(struct sockaddr_atmpvc) : sizeof(addr)) < 0) { + perror("connect"); + return -1; + } + addattr_l(n, 1024, TCA_OPTIONS, &s, sizeof(s)); + return 0; +} + + + +static int atm_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) +{ + char buffer[MAX_ATM_ADDR_LEN+1]; + + if (!opt) return 0; + if (RTA_PAYLOAD(opt) != sizeof(struct sockaddr_atmpvc)) return -EINVAL; + if (atm2text(buffer,MAX_ATM_ADDR_LEN,RTA_DATA(opt), + A2T_PRETTY | A2T_NAME) < 0) fprintf(stderr,"atm2text error\n"); + printf("%s",buffer); + return 0; +} + +static int atm_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats) +{ + return 0; +} + + +struct qdisc_util atm_util = { + NULL, + "atm", + atm_parse_opt, + atm_print_opt, + atm_print_xstats, + + atm_parse_class_opt, + atm_print_opt +}; + diff -ur --new-file old/atm/ilmid/Makefile new/atm/ilmid/Makefile --- old/atm/ilmid/Makefile Mon Oct 20 23:28:22 1997 +++ new/atm/ilmid/Makefile Tue Aug 4 20:00:15 1998 @@ -11,7 +11,7 @@ default: all -all: ilmid +do_all: ilmid asn1/libasn1.a: @cd asn1; make diff -ur --new-file old/atm/led/lec_ctrl.c new/atm/led/lec_ctrl.c --- old/atm/led/lec_ctrl.c Mon Feb 2 14:35:01 1998 +++ new/atm/led/lec_ctrl.c Fri Jul 3 21:16:31 1998 @@ -411,7 +411,8 @@ svcinit_conn_info (p_conn_info); p_conn_info->addr.sas_family = AF_ATMSVC; - + p_conn_info->conqos.aal = ATM_AAL5; + /* Set the forward and backward Max CPCS-SDU Size */ switch(blli_codepoint) { case BLLI_CONTROL: diff -ur --new-file old/atm/lib/Makefile new/atm/lib/Makefile --- old/atm/lib/Makefile Wed Apr 15 19:34:38 1998 +++ new/atm/lib/Makefile Tue Aug 4 20:00:21 1998 @@ -12,7 +12,7 @@ SYSHDR=atm.h atmd.h atmsap.h arequipa.h OPTSYSHDR=stdint.h -all: libatm.a libatmd.a libarequipa.a +do_all: libatm.a libatmd.a libarequipa.a include ../Rules.make diff -ur --new-file old/atm/lib/atmd.h new/atm/lib/atmd.h --- old/atm/lib/atmd.h Thu Apr 16 10:23:59 1998 +++ new/atm/lib/atmd.h Tue Jul 28 15:41:44 1998 @@ -89,6 +89,18 @@ /*--------------------------- Unix domain sockets ---------------------------*/ + +#include +#include + + +typedef struct { + int s; /* socket */ + struct sockaddr_un addr; /* reply address */ + int size; /* address size */ +} UN_CTX; + + int un_create(const char *path,mode_t mode); /* @@ -122,6 +134,20 @@ * send. The data is taken from the buffer. If any system call fails, un_reply * returns a negative value. Otherwise, is returns whatever was returned by the * handler function. + */ + +int un_recv(UN_CTX *ctx,int s,void *buf,int size); + +/* + * Receive a message into the specified buffer and store the information needed + * to send a reply in ctx. Sets errno and returns a negative value on error. + */ + +int un_send(const UN_CTX *ctx,void *buf,int len); + +/* + * Send a reply to the sender identified by ctx. Sets errno and returns a + * negative value on error. */ #endif diff -ur --new-file old/atm/lib/unix.c new/atm/lib/unix.c --- old/atm/lib/unix.c Thu Apr 16 15:42:46 1998 +++ new/atm/lib/unix.c Tue Jul 28 15:42:05 1998 @@ -71,20 +71,34 @@ } +int un_recv(UN_CTX *ctx,int s,void *buf,int size) +{ + ctx->s = s; + ctx->size = sizeof(ctx->addr); + return recvfrom(s,buf,size,0,(struct sockaddr *) &ctx->addr,&ctx->size); +} + + +int un_send(const UN_CTX *ctx,void *buf,int len) +{ + int sent; + + sent = sendto(ctx->s,buf,len,0,(struct sockaddr *) &ctx->addr,ctx->size); + if (sent < 0 || sent == len) return sent; + errno = EMSGSIZE; /* ugly */ + return -1; +} + + int un_reply(int s,void *buf,int size, int (*handler)(void *buf,int len,void *user),void *user) { - struct sockaddr_un addr; - int addr_size; - int len,sent; + UN_CTX ctx; + int len; - addr_size = sizeof(addr); - len = recvfrom(s,buf,size,0,(struct sockaddr *) &addr,&addr_size); + len = un_recv(&ctx,s,buf,size); if (len < 0) return len; len = handler(buf,len,user); if (len <= 0) return len; - sent = sendto(s,buf,len,0,(struct sockaddr *) &addr,addr_size); - if (sent < 0 || sent == len) return sent; - errno = EMSGSIZE; /* ugly */ - return -1; + return un_send(&ctx,buf,len); } diff -ur --new-file old/atm/maint/atmtcp.8 new/atm/maint/atmtcp.8 --- old/atm/maint/atmtcp.8 Thu Jun 25 10:42:15 1998 +++ new/atm/maint/atmtcp.8 Tue Aug 4 17:57:20 1998 @@ -1,28 +1,32 @@ -.TH ATMTCP 8 "June 25, 1998" "Linux" "Maintenance Commands" +.TH ATMTCP 8 "August 4, 1998" "Linux" "Maintenance Commands" .SH NAME atmtcp \- set up ATM over TCP connections .SH SYNOPSIS .ad l .B atmtcp -.RB [ -b ] -.RB [ -i \fIitf\fB ] +.RB [ \-b ] +.RB [ \-i\ \fIitf\fB ] .B \-l .RB [ \fIlclport\fB ] .br .B atmtcp -.RB [ -b ] -.RB [ -i \fIitf\fB ] +.RB [ \-b ] +.RB [ \-i\ \fIitf\fB ] .B \-c .I host .RB [ \fIrmtport\fB ] .br .B atmtcp -.RB [ -b ] -.RB [ -i \fIitf\fB ] +.RB [ \-b ] +.RB [ \-i\ \fIitf\fB ] .B \-s .I host .I line .RB [ \fIrmtport\fB ] +.br +\fBatmtcp\fP \fB\-p\fP [[\fB\-i\fP] \fIitf\fP] +.br +\fBatmtcp\fP \fB\-r\fP [[\fB\-i\fP] \fIitf\fP] .ad b .SH DESCRIPTION .B atmtcp @@ -31,6 +35,25 @@ ATM adapters linked by a cable or fiber, i.e. SDUs sent on a given VPI/VCI are received at the other end on the same VPI/VCI. .PP +.B atmtcp +can operate with two types of interfaces: ephemeral or persistent. +By default, +.B atmtcp +interfaces ephemeral. When the +.B atmtcp +process that created an interface terminates, the virtual ATM device is removed +as soon all VCs are closed. +However, if the interface was previously created +as a persistent interface, only the communication stops, but the interface +and all VCs on it remain intact. Attempts to send data on an +.B atmtcp +interface in this state fail silently, i.e. the interface behaves just like +a real ATM interface without a wire. +A new +.B atmtcp +process can then attach to the interface and resume operation. Persistent +interfaces need to be removed explicitly. +.PP The optional port arguments are used to run .B atmtcp on a different port than the default port (8401). @@ -46,15 +69,18 @@ connect to an instance of \fBatmtcp\fP running on the specified host. .IP \fB\-s\ \fIhost\fP\ \fIline\fP connect to an \fBatmtcp\fP "switch", attaching to the specified virtual line. +.IP \fB\-p\fP +create a persistent interface. +.IP \fB\-r\fP +remove a persistent interface. If the interface is still in use, it is marked +as non-persistent and will be removed as soon as all VCs are closed. .SH RESTRICTIONS Only AAL SDUs are exchanged, no segmentation or reassembly is performed. That implies that using different AALs (e.g. AAL5 and AAL0) on either side will reveal limitations of this emulation. +.PP .B atmtcp -continues to run during the the whole lifetime of the connection. Forcibly -terminating -.B atmtcp -will force all VCs to be closed and the virtual ATM device to be removed. +continues to run during the the whole lifetime of the connection. .SH AUTHOR Werner Almesberger, EPFL ICA .SH "SEE ALSO" diff -ur --new-file old/atm/maint/atmtcp.c new/atm/maint/atmtcp.c --- old/atm/maint/atmtcp.c Thu Jun 25 10:43:15 1998 +++ new/atm/maint/atmtcp.c Tue Aug 4 17:48:06 1998 @@ -123,13 +123,18 @@ name); fprintf(stderr,"%s [ -b ] [ -d ] [ -i itf ] -s " "[ ]\n",name); + fprintf(stderr,"%s -p [ [ -i ] itf ]\n",name); + fprintf(stderr,"%s -r [ [ -i ] itf ]\n",name); + fprintf(stderr,"\n -b background\n -d debug\n -i interface\n"); + fprintf(stderr," -l listen\n -c connect\n -s connect to switch\n"); + fprintf(stderr," -p create persistent\n -r remove persistent\n"); exit(1); } int main(int argc,char **argv) { - enum { m_undefined,m_listen,m_connect,m_switch } mode; + enum { m_undefined,m_listen,m_connect,m_switch,m_create,m_remove } mode; struct sockaddr_in addr; const char *name; char *end; @@ -143,7 +148,8 @@ background = 0; host = line = NULL; /* for gcc */ itf = -1; - while ((c = getopt(argc,argv,"bdi:lc:s:")) != EOF) + port = 0; /* for gcc */ + while ((c = getopt(argc,argv,"bdi:lc:prs:")) != EOF) switch (c) { case 'b': background = 1; @@ -170,6 +176,14 @@ mode = m_switch; host = optarg; break; + case 'p': + if (mode != m_undefined) usage(name); + mode = m_create; + break; + case 'r': + if (mode != m_undefined) usage(name); + mode = m_remove; + break; default: usage(name); } @@ -185,9 +199,30 @@ if (argc > optind+1) usage(name); port = argc == optind+1 ? atoi(argv[optind]) : -1; break; + case m_remove: + /* fall through */ + case m_create: + if (background || debug) usage(name); + if (argc != optind && itf != -1) usage(name); + if (argc != optind+1) usage(name); + itf = strtoul(argv[optind],&end,10); + if (*end) usage(name); + break; default: abort(); } + if ((s_krn = socket(PF_ATMSVC,SOCK_DGRAM,0)) < 0) { + perror("socket"); + return 1; + } + if (mode == m_create || mode == m_remove) { + if (mode == m_remove && itf == -1) itf = 0; + if (ioctl(s_krn,mode == m_create ? ATMTCP_CREATE : ATMTCP_REMOVE,itf) + >= 0) return 0; + perror(mode == m_create ? + "ioctl ATMTCP_CREATE" : "ioctl ATMTCP_REMOVE"); + return 1; + } if ((s_tcp = socket(PF_INET,SOCK_STREAM,0)) < 0) { perror("socket"); return 1; @@ -199,10 +234,6 @@ * Create atmtcp interface before setting up the TCP connection in order * to make the assignment of interface numbers a bit more predictable. */ - if ((s_krn = socket(PF_ATMSVC,SOCK_DGRAM,0)) < 0) { - perror("socket"); - return 1; - } if ((itf = ioctl(s_krn,SIOCSIFATMTCP,itf)) < 0) { perror("ioctl SIOCSIFATMTCP"); return 1; diff -ur --new-file old/atm/mkdist new/atm/mkdist --- old/atm/mkdist Thu Jun 25 13:33:48 1998 +++ new/atm/mkdist Fri Jul 24 15:19:01 1998 @@ -12,7 +12,6 @@ make usage.txt cd ../.. tar cvf - \ - atm/WARNING \ atm/VERSION atm/README atm/README.DRIVERS atm/CREDITS atm/USAGE \ atm/CHANGES atm/BUGS \ atm/COPYING atm/COPYING.GPL atm/COPYING.LGPL \ @@ -117,6 +116,7 @@ atm/switch/tcp/README atm/switch/tcp/Makefile atm/switch/tcp/tcpsw.c \ atm/extra/extra.html atm/extra/Makefile atm/extra/tcpdump-3.0.4-1.patch \ atm/extra/bind-4.9.5-REL.patch atm/extra/hosts2ans.pl \ + atm/extra/tc/README atm/extra/tc/Makefile.patch atm/extra/tc/q_atm.c \ atm/config/README atm/config/Makefile atm/config\ atm/config/common/README atm/config/common/Makefile \ atm/config/common/hosts.atm atm/config/common/e164_cc \ @@ -129,3 +129,4 @@ # atm/atm-$VERSION-1.spec | gzip -9 >$ARCHDIR/atm-$VERSION.tar.gz #atm/bind-4.9.4.T4B.ATM.patch +# atm/WARNING \ diff -ur --new-file old/atm/qgen/msg.fmt new/atm/qgen/msg.fmt --- old/atm/qgen/msg.fmt Wed Feb 18 15:27:09 1998 +++ new/atm/qgen/msg.fmt Wed Jul 29 17:11:13 1998 @@ -1,6 +1,6 @@ /* msg.fmt - Signaling message format decription for UNI 3.0, 3.1, and 4.0 */ -/* Written 1995-1998 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #undef linux /* grr ... */ @@ -382,7 +382,7 @@ break invalid <8> # not supported } - ATM_CV_CI_ACC_INF_DISC,ATM_CV_INCOMP_DEST,ATM_CV_MAND_IE_MISSING, + ATM_CV_ACC_INF_DISC,ATM_CV_INCOMP_DEST,ATM_CV_MAND_IE_MISSING, ATM_CV_UNKNOWN_IE,ATM_CV_INVALID_IE { # Note 6 break ie_id6 <-224> diff -ur --new-file old/atm/qgen/uni.h new/atm/qgen/uni.h --- old/atm/qgen/uni.h Wed Nov 5 21:52:34 1997 +++ new/atm/qgen/uni.h Tue Jul 28 20:59:51 1998 @@ -1,6 +1,6 @@ /* uni.h - Various Q.2931/Q.2971/Q.2963.1/UNI 3.x/UNI 4.0 constants */ -/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ /* * Note: some values don't appear in UNI 3.0 or 3.1 but are taken from Q.2931 @@ -130,9 +130,9 @@ #define ATM_CV_CI_FAIL 36 /* VPCI/VCI assignment failure */ #define ATM_CV_UCR_UNAVAIL 37 /* user cell rate not available */ #endif -#define ATM_CV_CI_NET_OOO 38 /* network out of order - unused */ -#define ATM_CV_CI_TEMP_FAIL 41 /* temporary failure */ -#define ATM_CV_CI_ACC_INF_DISC 43 /* access information discarded */ +#define ATM_CV_NET_OOO 38 /* network out of order - unused */ +#define ATM_CV_TEMP_FAIL 41 /* temporary failure */ +#define ATM_CV_ACC_INF_DISC 43 /* access information discarded */ #define ATM_CV_NO_CI 45 /* no VPCI/VCI available */ #define ATM_CV_RES_UNAVAIL 47 /* resource unavailable, unspecified */ /* ----------------------------------- service or option not available */ diff -ur --new-file old/atm/saal/Makefile new/atm/saal/Makefile --- old/atm/saal/Makefile Thu Jul 3 15:38:24 1997 +++ new/atm/saal/Makefile Tue Aug 4 20:00:32 1998 @@ -1,7 +1,7 @@ LIBS= OBJS=pdu.o saal.o sscf.o sscop.o queue.o -all: libsaal.a +do_all: libsaal.a include ../Rules.make diff -ur --new-file old/atm/sigd/atmsigd.c new/atm/sigd/atmsigd.c --- old/atm/sigd/atmsigd.c Wed Jun 24 20:44:01 1998 +++ new/atm/sigd/atmsigd.c Tue Aug 4 00:30:25 1998 @@ -267,7 +267,7 @@ FILE *file; if (!status) return; - if (dump_dir) file = stderr; + if (!dump_dir) file = stderr; else { sprintf(path,"atmsigd.%d.trace.exit",getpid()); if (!(file = fopen(path,"w"))) { diff -ur --new-file old/atm/sigd/kernel.c new/atm/sigd/kernel.c --- old/atm/sigd/kernel.c Thu Jun 25 13:13:07 1998 +++ new/atm/sigd/kernel.c Fri Jul 3 22:20:29 1998 @@ -389,7 +389,7 @@ NULL); return; } - if (!sock || sock->state != ss_connected) { + if (!sock || sock->state != ss_connected || !sock->owner) { send_kernel(sock->id,0,as_okay,-EBADFD,NULL,NULL,NULL,NULL, NULL); return; diff -ur --new-file old/atm/sigd/proto.h new/atm/sigd/proto.h --- old/atm/sigd/proto.h Thu Jun 25 12:56:13 1998 +++ new/atm/sigd/proto.h Fri Jul 3 22:20:16 1998 @@ -45,6 +45,7 @@ struct atm_qos qos; /* QOS parameters */ #ifdef Q2963_1 struct atm_qos new_qos; /* during modification */ + int owner; /* non-zero if connection owner */ #endif int error; /* error code for close */ /* --- UNI information ------------------------------------------------- */ diff -ur --new-file old/atm/sigd/uni.c new/atm/sigd/uni.c --- old/atm/sigd/uni.c Thu Jun 25 12:53:42 1998 +++ new/atm/sigd/uni.c Fri Jul 3 22:21:44 1998 @@ -367,6 +367,9 @@ send_kernel(sock->id,0,as_okay,0,&sock->pvc,NULL,&sock->local, &sock->sap,&sock->qos); new_state(sock,ss_connected); +#ifdef Q2963_1 + sock->owner = 1; +#endif if (atm2text(buffer,MAX_ATM_ADDR_LEN+1,(struct sockaddr *) &sock->local,0) < 0) strcpy(buffer,""); diag(COMPONENT,DIAG_INFO,"Active open succeeded (CR 0x%06X, " @@ -384,6 +387,9 @@ send_kernel(sock->id,0,as_okay,0,NULL,NULL,&sock->local,&sock->sap, NULL); new_state(sock,ss_connected); +#ifdef Q2963_1 + sock->owner = 0; +#endif if (atm2text(buffer,MAX_ATM_ADDR_LEN+1, (struct sockaddr *) &sock->local,0) < 0) strcpy(buffer,""); diag(COMPONENT,DIAG_INFO,"Passive open succeeded (CR 0x%06X, " @@ -552,7 +558,7 @@ * Buglet ahead: should actually test "call_state" */ case ATM_MSG_MODIFY_REQ: - if (sock->state != ss_connected) break; + if (sock->state != ss_connected || sock->owner) break; sock->new_qos = sock->qos; if (q_present(&in_dsc,QF_fw_pcr_01)) sock->new_qos.rxtp.max_pcr = q_fetch(&in_dsc,QF_fw_pcr_01); @@ -580,7 +586,7 @@ new_state(sock,ss_mod_fin_fail); return; case ATM_MSG_CONN_AVAIL: - if (sock->state != ss_connected) break; + if (sock->state != ss_connected || !sock->owner) break; STOP_TIMER(sock); send_kernel(sock->id,0,as_modify,ATM_MF_SET,NULL,NULL,NULL,NULL, &sock->qos); diff -ur --new-file old/atm/switch/Makefile new/atm/switch/Makefile --- old/atm/switch/Makefile Thu Jun 25 13:34:24 1998 +++ new/atm/switch/Makefile Tue Aug 4 20:00:38 1998 @@ -1,13 +1,9 @@ SW_OBJS=dispatch.o proto.o relay.o route.o sig.o lex.yy.o y.tab.o -SWITCHES=debug tcp +SUBDIRS=debug tcp -all: libsw.a +do_all: libsw.a include ../Rules.make - -do_all: - for n in $(SWITCHES); do \ - $(MAKE) -C $$n || exit; done lex.yy.c: cfg.l y.tab.h ../lib/atm.h $(LEX) cfg.l diff -ur --new-file old/atm/switch/debug/Makefile new/atm/switch/debug/Makefile --- old/atm/switch/debug/Makefile Thu Jun 18 16:24:13 1998 +++ new/atm/switch/debug/Makefile Tue Aug 4 19:55:05 1998 @@ -1,5 +1,6 @@ LIBS=-lsw -latmd -L.. LIBDEPS=../../lib/libatmd.a ../libsw.a +INCLUDES=-I../../qgen OBJS=debug.o SYSPGMS=sw_debug diff -ur --new-file old/atm/switch/debug/debug.c new/atm/switch/debug/debug.c --- old/atm/switch/debug/debug.c Wed Jun 24 12:19:27 1998 +++ new/atm/switch/debug/debug.c Tue Aug 4 19:55:44 1998 @@ -8,6 +8,7 @@ #include #include +#include "uni.h" #include "../fab.h" @@ -85,7 +86,7 @@ void fab_op(CALL *call,int op,const struct atm_qos *qos, - void (*callback)(CALL *call,int okay,void *user),void *user) + void (*callback)(CALL *call,int cause,void *more,void *user),void *user) { diag(COMPONENT,DIAG_INFO,"fab_op%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", !op ? " FREE" : "",op & RM_RSV(_RM_ANY) ? " RM_RSV:" : "", @@ -101,13 +102,13 @@ op & _RM_SHIFT(RM_PATH_RX) ? " PATH_RX" : ""); if (op & (RM_RSV(RM_IN) | RM_CLAIM(RM_IN))) if (!check_ci(&call->in.pvc)) { - callback(call,0,user); + callback(call,ATM_CV_CI_UNAVAIL,NULL,user); return; } if (op & (RM_RSV(RM_OUT) | RM_CLAIM(RM_OUT))) if (!check_ci(&call->out.pvc)) { - callback(call,0,user); + callback(call,ATM_CV_CI_UNAVAIL,NULL,user); return; } - callback(call,1,user); + callback(call,0,NULL,user); } diff -ur --new-file old/atm/switch/fab.h new/atm/switch/fab.h --- old/atm/switch/fab.h Wed Jun 24 10:28:42 1998 +++ new/atm/switch/fab.h Tue Aug 4 19:50:46 1998 @@ -64,6 +64,6 @@ */ void fab_op(CALL *call,int op,const struct atm_qos *qos, - void (*callback)(CALL *call,int okay,void *user),void *user); + void (*callback)(CALL *call,int cause,void *more,void *user),void *user); #endif diff -ur --new-file old/atm/switch/relay.c new/atm/switch/relay.c --- old/atm/switch/relay.c Thu Jun 25 11:05:21 1998 +++ new/atm/switch/relay.c Tue Aug 4 19:50:15 1998 @@ -28,14 +28,14 @@ extern FILE *yyin; -static void from_fab(CALL *call,int okay,void *user) +static void from_fab(CALL *call,int cause,void *more,void *user) { - printf("%p: fab returns %d\n",call,okay); + printf("%p: fab returns cause %d\n",call,cause); print_call(call); switch (call->state) { case cs_indicated: - if (okay) { + if (!cause) { /* send connect to called and enter state cs_rm_accepted */ send_identify(call); send_connect(call); @@ -43,26 +43,26 @@ } else { /* send as_reject to caller and enter state cs_invalid */ - send_reject_not_id(call->in.sig,-EREMOTEIO); /* @@@ */ + send_reject_not_id(call->in.sig,-EREMOTEIO); /* @@@ use cause*/ new_state(call,cs_invalid); free_call(call); } break; case cs_called_accepted: - if (okay) { + if (!cause) { /* send accept to caller */ send_accept(call); new_state(call,cs_rm_accepted2); } else { /* send reject to caller and close to called */ - send_reject(call,-EREMOTEIO); + send_reject(call,-EREMOTEIO); /* @@@ use cause */ send_close(call,CALLED); new_state(call,cs_rejected); } break; case cs_rejecting: - if (!okay) free_call(call); + if (cause) free_call(call); else { /* free resources */ new_state(call, cs_free_rm); @@ -70,7 +70,7 @@ } break; case cs_free_rm: - if (!okay) printf("Error: RM couldn't free resources\n"); + if (cause) printf("Error: RM couldn't free resources\n"); free_call(call); break; default: diff -ur --new-file old/atm/switch/sig.c new/atm/switch/sig.c --- old/atm/switch/sig.c Thu Jun 25 12:49:15 1998 +++ new/atm/switch/sig.c Tue Aug 4 19:53:55 1998 @@ -80,13 +80,13 @@ } -static void up_callback(CALL *call,int okay,void *user) +static void up_callback(CALL *call,int cause,void *more,void *user) { SIGNALING_ENTITY *sig = user; int error; - if (!okay) { - diag(COMPONENT,DIAG_ERROR,"up_callback: error"); + if (cause) { + diag(COMPONENT,DIAG_ERROR,"up_callback: error (cause %d)",cause); return; } if (sig->command) system(sig->command); @@ -111,9 +111,10 @@ } -static void down_callback(CALL *call,int okay,void *user) +static void down_callback(CALL *call,int cause,void *more,void *user) { - if (!okay) diag(COMPONENT,DIAG_ERROR,"down_callback: error"); + if (cause) + diag(COMPONENT,DIAG_ERROR,"down_callback: error (cause %d)",cause); } diff -ur --new-file old/atm/switch/tcp/Makefile new/atm/switch/tcp/Makefile --- old/atm/switch/tcp/Makefile Wed Jun 24 10:35:10 1998 +++ new/atm/switch/tcp/Makefile Tue Aug 4 19:55:00 1998 @@ -1,5 +1,6 @@ LIBS=-lsw -latmd -L.. LIBDEPS=../../lib/libatmd.a ../libsw.a +INCLUDES=-I../../qgen OBJS=tcpsw.o SYSPGMS=sw_tcp diff -ur --new-file old/atm/switch/tcp/tcpsw.c new/atm/switch/tcp/tcpsw.c --- old/atm/switch/tcp/tcpsw.c Thu Jun 25 13:59:20 1998 +++ new/atm/switch/tcp/tcpsw.c Tue Aug 4 19:56:13 1998 @@ -12,10 +12,11 @@ #include #include +#include #include - #include +#include "uni.h" #include "../fab.h" #include "../dispatch.h" @@ -356,7 +357,7 @@ void fab_op(CALL *call,int op,const struct atm_qos *qos, - void (*callback)(CALL *call,int okay,void *user),void *user) + void (*callback)(CALL *call,int cause,void *more,void *user),void *user) { int error,error2; @@ -374,12 +375,12 @@ op & _RM_SHIFT(RM_PATH_RX) ? " PATH_RX" : ""); if (op & (RM_RSV(RM_IN) | RM_CLAIM(RM_IN))) if (!check_ci(&call->in.pvc)) { - callback(call,0,user); + callback(call,ATM_CV_CI_UNAVAIL,NULL,user); return; } if (op & (RM_RSV(RM_OUT) | RM_CLAIM(RM_OUT))) if (!check_ci(&call->out.pvc)) { - callback(call,0,user); + callback(call,ATM_CV_CI_UNAVAIL,NULL,user); return; } if (op & RM_CLAIM(RM_PATH)) { @@ -394,7 +395,7 @@ } if (error) { diag(COMPONENT,DIAG_ERROR,"add_entry: %s",strerror(error)); - callback(call,0,user); + callback(call,ATM_CV_RES_UNAVAIL,NULL,user); return; } PRV(call)->active = 1; @@ -407,9 +408,9 @@ if (error2) diag(COMPONENT,DIAG_ERROR,"del_entry: %s",strerror(error2)); if (error || error2) { - callback(call,0,user); + callback(call,ATM_CV_TEMP_FAIL,NULL,user); return; } } - callback(call,1,user); + callback(call,0,NULL,user); } .