summaryrefslogtreecommitdiffstats
path: root/sys/netatm/ipatm/ipatm_event.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1998-09-15 08:23:17 +0000
committerphk <phk@FreeBSD.org>1998-09-15 08:23:17 +0000
commitc3dd1fa899d435ea4bf79897f646a93cb80c94ac (patch)
tree98dfbc96e3c6aa7ff1f322855f6484c4e609819d /sys/netatm/ipatm/ipatm_event.c
parent9ed6892f4808d56de443849229e151f8f7ad43b0 (diff)
downloadFreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.zip
FreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.tar.gz
Add new files for HARP3
Host ATM Research Platform (HARP), Network Computing Services, Inc. This software was developed with the support of the Defense Advanced Research Projects Agency (DARPA).
Diffstat (limited to 'sys/netatm/ipatm/ipatm_event.c')
-rw-r--r--sys/netatm/ipatm/ipatm_event.c454
1 files changed, 454 insertions, 0 deletions
diff --git a/sys/netatm/ipatm/ipatm_event.c b/sys/netatm/ipatm/ipatm_event.c
new file mode 100644
index 0000000..048edf9
--- /dev/null
+++ b/sys/netatm/ipatm/ipatm_event.c
@@ -0,0 +1,454 @@
+/*
+ *
+ * ===================================
+ * HARP | Host ATM Research Platform
+ * ===================================
+ *
+ *
+ * This Host ATM Research Platform ("HARP") file (the "Software") is
+ * made available by Network Computing Services, Inc. ("NetworkCS")
+ * "AS IS". NetworkCS does not provide maintenance, improvements or
+ * support of any kind.
+ *
+ * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
+ * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
+ * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
+ * In no event shall NetworkCS be responsible for any damages, including
+ * but not limited to consequential damages, arising from or relating to
+ * any use of the Software or related support.
+ *
+ * Copyright 1994-1998 Network Computing Services, Inc.
+ *
+ * Copies of this Software may be made, however, the above copyright
+ * notice must be reproduced on all copies.
+ *
+ * @(#) $Id: ipatm_event.c,v 1.8 1998/08/06 18:21:13 mks Exp $
+ *
+ */
+
+/*
+ * IP Over ATM Support
+ * -------------------
+ *
+ * IP VCC event handler
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: ipatm_event.c,v 1.8 1998/08/06 18:21:13 mks Exp $";
+#endif
+
+#include <netatm/kern_include.h>
+
+#include <netatm/ipatm/ipatm.h>
+#include <netatm/ipatm/ipatm_var.h>
+#include <netatm/ipatm/ipatm_serv.h>
+
+
+/*
+ * Process an IP VCC timeout
+ *
+ * Called when a previously scheduled ipvcc control block timer expires.
+ * Processing will be based on the current ipvcc state.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * tip pointer to ipvcc timer control block
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+ipatm_timeout(tip)
+ struct atm_time *tip;
+{
+ struct ipvcc *ivp;
+
+ /*
+ * Back-off to ipvcc control block
+ */
+ ivp = (struct ipvcc *)
+ ((caddr_t)tip - (int)(&((struct ipvcc *)0)->iv_time));
+
+ /*
+ * Process timeout based on protocol state
+ */
+ switch (ivp->iv_state) {
+
+ case IPVCC_PMAP:
+ /*
+ * Give up waiting for arp response
+ */
+ (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
+ break;
+
+ case IPVCC_POPEN:
+ case IPVCC_PACCEPT:
+ /*
+ * Give up waiting for signalling manager response
+ */
+ (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
+ break;
+
+ case IPVCC_ACTPENT:
+ /*
+ * Try again to get an ARP entry
+ */
+ switch ((*ivp->iv_ipnif->inf_serv->is_arp_pvcopen)(ivp)) {
+
+ case MAP_PROCEEDING:
+ /*
+ * Wait for answer
+ */
+ ivp->iv_state = IPVCC_ACTIVE;
+ break;
+
+ case MAP_VALID:
+ /*
+ * We've got our answer already
+ */
+ ivp->iv_state = IPVCC_ACTIVE;
+ ivp->iv_flags |= IVF_MAPOK;
+ ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
+ break;
+
+ case MAP_FAILED:
+ /*
+ * Try again later
+ */
+ IPVCC_TIMER(ivp, 5 * ATM_HZ);
+ break;
+
+ default:
+ panic("ipatm_timeout: invalid am_pvcopen return");
+ }
+ break;
+
+ default:
+ log(LOG_ERR, "ipatm: invalid timer state: ivp=0x%x, state=%d\n",
+ (int)ivp, ivp->iv_state);
+ }
+}
+
+
+/*
+ * Process IP VCC Connected Notification
+ *
+ * Arguments:
+ * toku owner's connection token (ipvcc protocol block)
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+ipatm_connected(toku)
+ void *toku;
+{
+ struct ipvcc *ivp = (struct ipvcc *)toku;
+
+ /*
+ * SVC is connected
+ */
+ if ((ivp->iv_state != IPVCC_POPEN) &&
+ (ivp->iv_state != IPVCC_PACCEPT)) {
+ log(LOG_ERR, "ipatm: invalid CALL_CONNECTED state=%d\n",
+ ivp->iv_state);
+ return;
+ }
+
+ /*
+ * Verify possible negotiated parameter values
+ */
+ if (ivp->iv_state == IPVCC_POPEN) {
+ Atm_attributes *ap = &ivp->iv_conn->co_connvc->cvc_attr;
+ int mtu = (ivp->iv_flags & IVF_LLC) ?
+ ATM_NIF_MTU + IPATM_LLC_LEN :
+ ATM_NIF_MTU;
+
+ /*
+ * Verify final MTU
+ */
+ if (ap->aal.type == ATM_AAL5) {
+ if ((ap->aal.v.aal5.forward_max_SDU_size < mtu) ||
+ (ap->aal.v.aal5.backward_max_SDU_size > mtu)) {
+ (void) ipatm_closevc(ivp,
+ T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
+ return;
+ }
+ } else {
+ if ((ap->aal.v.aal4.forward_max_SDU_size < mtu) ||
+ (ap->aal.v.aal4.backward_max_SDU_size > mtu)) {
+ (void) ipatm_closevc(ivp,
+ T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
+ return;
+ }
+ }
+ }
+
+ /*
+ * Finish up VCC activation
+ */
+ ipatm_activate(ivp);
+}
+
+
+/*
+ * Process IP VCC Cleared Notification
+ *
+ * Arguments:
+ * toku owner's connection token (ipvcc protocol block)
+ * cause pointer to cause code
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+ipatm_cleared(toku, cause)
+ void *toku;
+ struct t_atm_cause *cause;
+{
+ struct ipvcc *ivp = (struct ipvcc *)toku;
+
+
+ /*
+ * VCC has been cleared, so figure out what's next
+ */
+ ivp->iv_conn = NULL;
+
+ switch (ivp->iv_state) {
+
+ case IPVCC_POPEN:
+ /*
+ * Call setup failed, see if there is another
+ * set of vcc parameters to try
+ */
+ ivp->iv_state = IPVCC_CLOSED;
+ if (ipatm_retrysvc(ivp)) {
+ (void) ipatm_closevc(ivp, cause->cause_value);
+ }
+ break;
+
+ case IPVCC_PACCEPT:
+ case IPVCC_ACTPENT:
+ case IPVCC_ACTIVE:
+ ivp->iv_state = IPVCC_CLOSED;
+ (void) ipatm_closevc(ivp, cause->cause_value);
+ break;
+ }
+}
+
+
+/*
+ * Process an ARP Event Notification
+ *
+ * Arguments:
+ * ivp pointer to IP VCC control block
+ * event ARP event type
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+ipatm_arpnotify(ivp, event)
+ struct ipvcc *ivp;
+ int event;
+{
+ struct sockaddr_in sin;
+ struct ifnet *ifp;
+
+ /*
+ * Process event
+ */
+ switch (event) {
+
+ case MAP_VALID:
+ switch (ivp->iv_state) {
+
+ case IPVCC_PMAP:
+ /*
+ * We've got our destination, however, first we'll
+ * check to make sure no other VCC to our destination
+ * has also had it's ARP table entry completed.
+ * If we don't find a better VCC to use, then we'll
+ * go ahead and open this SVC.
+ */
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
+ if (ipatm_iptovc(&sin, ivp->iv_ipnif->inf_nif) != ivp) {
+ /*
+ * We found a better VCC, so use it and
+ * get rid of this VCC
+ */
+ if (ivp->iv_queue) {
+ ifp = (struct ifnet *)
+ ivp->iv_ipnif->inf_nif;
+ (void) ipatm_ifoutput(ifp,
+ ivp->iv_queue,
+ (struct sockaddr *)&sin);
+ ivp->iv_queue = NULL;
+ }
+ (void) ipatm_closevc(ivp,
+ T_ATM_CAUSE_UNSPECIFIED_NORMAL);
+
+ } else {
+ /*
+ * We like this VCC...
+ */
+ ivp->iv_flags |= IVF_MAPOK;
+ if (ipatm_opensvc(ivp)) {
+ (void) ipatm_closevc(ivp,
+ T_ATM_CAUSE_TEMPORARY_FAILURE);
+ }
+ }
+ break;
+
+ case IPVCC_POPEN:
+ case IPVCC_PACCEPT:
+ case IPVCC_ACTIVE:
+ /*
+ * Everything looks good, so accept new mapping
+ */
+ ivp->iv_flags |= IVF_MAPOK;
+ ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
+
+ /*
+ * Send queued packet
+ */
+ if ((ivp->iv_state == IPVCC_ACTIVE) && ivp->iv_queue) {
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
+ ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
+ (void) ipatm_ifoutput(ifp, ivp->iv_queue,
+ (struct sockaddr *)&sin);
+ ivp->iv_queue = NULL;
+ }
+ break;
+ }
+ break;
+
+ case MAP_INVALID:
+ switch (ivp->iv_state) {
+
+ case IPVCC_POPEN:
+ case IPVCC_PACCEPT:
+ case IPVCC_ACTIVE:
+
+ /*
+ * Mapping has gone stale, so we cant use this VCC
+ * until the mapping is refreshed
+ */
+ ivp->iv_flags &= ~IVF_MAPOK;
+ break;
+ }
+ break;
+
+ case MAP_FAILED:
+ /*
+ * ARP lookup failed, just trash it all
+ */
+ (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
+ break;
+
+ case MAP_CHANGED:
+ /*
+ * ARP mapping has changed
+ */
+ if (ivp->iv_flags & IVF_PVC) {
+ /*
+ * For PVCs, just reset lookup cache if needed
+ */
+ if (last_map_ipvcc == ivp) {
+ last_map_ipdst = 0;
+ last_map_ipvcc = NULL;
+ }
+ } else {
+ /*
+ * Close SVC if it has already used this mapping
+ */
+ switch (ivp->iv_state) {
+
+ case IPVCC_POPEN:
+ case IPVCC_ACTIVE:
+ (void) ipatm_closevc(ivp,
+ T_ATM_CAUSE_UNSPECIFIED_NORMAL);
+ break;
+ }
+ }
+ break;
+
+ default:
+ log(LOG_ERR, "ipatm: unknown arp event %d, ivp=0x%x\n",
+ event, (int)ivp);
+ }
+}
+
+
+/*
+ * Process an IP VCC idle timer tick
+ *
+ * This function is called every IPATM_IDLE_TIME seconds, in order to
+ * scan for idle IP VCC's. If an active VCC reaches the idle time limit,
+ * then it will be closed.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * tip pointer to the VCC idle timer control block
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+ipatm_itimeout(tip)
+ struct atm_time *tip;
+{
+ struct ipvcc *ivp, *inext;
+ struct ip_nif *inp;
+
+
+ /*
+ * Schedule next timeout
+ */
+ atm_timeout(&ipatm_itimer, IPATM_IDLE_TIME, ipatm_itimeout);
+
+ /*
+ * Check for disabled idle timeout
+ */
+ if (ipatm_vcidle == 0)
+ return;
+
+ /*
+ * Check out all IP VCCs
+ */
+ for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
+ for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
+ ivp = inext) {
+
+ inext = Q_NEXT(ivp, struct ipvcc, iv_elem);
+
+ /*
+ * Looking for active, idle SVCs
+ */
+ if (ivp->iv_flags & (IVF_PVC | IVF_NOIDLE))
+ continue;
+ if (ivp->iv_state != IPVCC_ACTIVE)
+ continue;
+ if (++ivp->iv_idle < ipatm_vcidle)
+ continue;
+
+ /*
+ * OK, we found one - close the VCC
+ */
+ (void) ipatm_closevc(ivp,
+ T_ATM_CAUSE_UNSPECIFIED_NORMAL);
+ }
+ }
+}
+
OpenPOWER on IntegriCloud