Esempio n. 1
0
/*
 * Process a SPANS ARP retry timer tick
 * 
 * This function is called every SPANSARP_RETRY seconds, in order to retry
 * awaiting arp resolution requests.  We will retry requests indefinitely,
 * assuming that IP will set a timeout to close the VCC(s) requesting the
 * failing address resolution.
 *
 * Called from a critical section.
 *
 * Arguments:
 *	tip	pointer to spansarp retry timer control block
 *
 * Returns:
 *	none
 *
 */
static void
spansarp_retry(struct atm_time *tip)
{
	struct spansarp	*sap;


	/*
	 * See if there's work to do
	 */
	if (spansarp_retry_head == NULL) {
		return;
	}

	/*
	 * Schedule next timeout
	 */
	atm_timeout(&spansarp_rtimer, SPANSARP_RETRY, spansarp_retry);

	/*
	 * Run through retry chain, (re)issuing arp requests.
	 */
	for (sap = spansarp_retry_head; sap; sap = sap->sa_next) {

		/*
		 * Send another arp request
		 */
		spansarp_request(sap);
	}
}
Esempio n. 2
0
/*
 * Initialize driver processing
 * 
 * This will be called during module loading.  Not much to do here, as
 * we must wait for our identify/attach routines to get called before
 * we know what we're in for.
 *
 * Arguments:
 *	none
 *
 * Returns:
 *	0 	startup was successful 
 *	errno	startup failed - reason indicated
 *
 */
static int
fore_start()
{

	/*
	 * Verify software version
	 */
	if (atm_version != ATM_VERSION) {
		log(LOG_ERR, "version mismatch: fore=%d.%d kernel=%d.%d\n",
			ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
			ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
		return (EINVAL);
	}

	/*
	 * Initialize DMA mapping
	 */
	DMA_INIT();

	/*
	 * Start up watchdog timer
	 */
	atm_timeout(&fore_timer, ATM_HZ * FORE_TIME_TICK, fore_timeout);

	fore_inited = 1;

	return (0);
}
Esempio n. 3
0
/*
 * Initialize ATM kernel
 * 
 * Performs any initialization required before things really get underway.
 * Called from ATM domain initialization or from first registration function 
 * which gets called.
 *
 * Arguments:
 *	none
 *
 * Returns:
 *	none
 *
 */
void
atm_initialize(void)
{
	/*
	 * Never called from interrupts, so no locking needed
	 */
	if (atm_init)
		return;
	atm_init = 1;

	atm_intrq.ifq_maxlen = ATM_INTRQ_MAX;
	netisr_register(NETISR_ATM, atm_intr, NULL);

	/*
	 * Initialize subsystems
	 */
	atm_aal5_init();

	/*
	 * Prime the timer
	 */
	callout_init(&atm_timexp_ch);
	callout_reset(&atm_timexp_ch, hz / ATM_HZ, atm_timexp, NULL);

	/*
	 * Start the compaction timer
	 */
	atm_timeout(&atm_compactimer, SPOOL_COMPACT, atm_compact);
}
Esempio n. 4
0
/*
 * Process IP Network Interface Activation
 * 
 * Called whenever an IP network interface becomes active.
 *
 * Called from a critical section.
 *
 * Arguments:
 *      clp     pointer to CLS interface
 *
 * Returns:
 *      none
 *
 */
void
spansarp_ipact(struct spanscls *clp)
{
	/*
	 * Make sure aging timer is running
	 */
	if ((spansarp_timer.ti_flag & TIF_QUEUED) == 0)
		atm_timeout(&spansarp_timer, SPANSARP_AGING, spansarp_aging);
}
Esempio n. 5
0
/*
 * Initialize ATM kernel
 * 
 * Performs any initialization required before things really get underway.
 * Called from ATM domain initialization or from first registration function 
 * which gets called.
 *
 * Arguments:
 *	none
 *
 * Returns:
 *	none
 *
 */
void
atm_initialize()
{
	/*
	 * Never called from interrupts, so no locking needed
	 */
	if (atm_init)
		return;
	atm_init = 1;

#ifndef __FreeBSD__
	/*
	 * Add ATM protocol family
	 */
	(void) protocol_family(&atmdomain, NULL, NULL);
#endif

	atm_intrq.ifq_maxlen = ATM_INTRQ_MAX;
#ifdef sgi
	atm_intr_index = register_isr(atm_intr);
#endif

	/*
	 * Initialize subsystems
	 */
	atm_aal5_init();

	/*
	 * Prime the timer
	 */
	(void) timeout(atm_timexp, (void *)0, hz/ATM_HZ);

	/*
	 * Start the compaction timer
	 */
	atm_timeout(&atm_compactimer, SPOOL_COMPACT, atm_compact);
}
Esempio n. 6
0
/*
 * Process a new outgoing SVC requiring SPANS ARP support
 * 
 * This function is called by an endpoint wishing to resolve a destination 
 * IP address to an ATM address in order to open an SVC to that destination.
 * If a valid mapping is already in our cache, then we just tell the caller
 * about it and that's that.  Otherwise, we have to allocate a new arp entry
 * and issue a query for the mapping.
 *
 * Arguments:
 *	ivp	pointer to SVC's IPVCC control block
 *	dst	pointer to destination IP address
 *
 * Returns:
 *	MAP_VALID	- Got the answer, returned via iv_arpent field.
 *	MAP_PROCEEDING	- OK so far, querying for peer's mapping
 *	MAP_FAILED	- error, unable to allocate resources
 *
 */
int
spansarp_svcout(struct ipvcc *ivp, struct in_addr *dst)
{
	struct spanscls	*clp;
	struct spansarp	*sap;

	ivp->iv_arpent = NULL;

	/*
	 * Lookup destination address
	 */
	crit_enter();
	SPANSARP_LOOKUP(dst->s_addr, sap);

	if (sap) {
		/*
		 * Link this vcc to entry queue
		 */
		LINK2TAIL(ivp, struct ipvcc, sap->sa_ivp, iv_arpnext);

		/*
		 * If entry is valid, we're done
		 */
		if (sap->sa_flags & SAF_VALID) {
			ivp->iv_arpent = (struct arpmap *)sap;
			crit_exit();
			return (MAP_VALID);
		}

		/*
		 * We're already looking for this address
		 */
		crit_exit();
		return (MAP_PROCEEDING);
	}

	/*
	 * Need a new arp entry - first, find the cls instance
	 * corresponding to the requestor's IP interface.
	 */
	for (clp = spanscls_head; clp; clp = clp->cls_next) {
		if (clp->cls_ipnif == ivp->iv_ipnif)
			break;
	}
	if (clp == NULL) {
		crit_exit();
		return (MAP_FAILED);
	}

	/*
	 * Now get the new arp entry
	 */
	sap = (struct spansarp *)atm_allocate(&spansarp_pool);
	if (sap == NULL) {
		crit_exit();
		return (MAP_FAILED);
	}

	/*
	 * Get entry set up
	 */
	sap->sa_dstip.s_addr = dst->s_addr;
	sap->sa_dstatm.address_format = T_ATM_ABSENT;
	sap->sa_dstatm.address_length = 0;
	sap->sa_dstatmsub.address_format = T_ATM_ABSENT;
	sap->sa_dstatmsub.address_length = 0;
	sap->sa_cls = clp;
	sap->sa_origin = SAO_LOOKUP;

	/*
	 * Link ipvcc to arp entry for later notification
	 */
	LINK2TAIL(ivp, struct ipvcc, sap->sa_ivp, iv_arpnext);

	/*
	 * Add arp entry to table
	 */
	SPANSARP_ADD(sap);

	/*
	 * Add arp entry to retry list and start retry timer if needed
	 */
	LINK2TAIL(sap, struct spansarp, spansarp_retry_head, sa_rnext);
	if ((spansarp_rtimer.ti_flag & TIF_QUEUED) == 0)
		atm_timeout(&spansarp_rtimer, SPANSARP_RETRY, spansarp_retry);

	/*
	 * Issue arp request for this address
	 */
	spansarp_request(sap);

	crit_exit();
	return (MAP_PROCEEDING);
}
Esempio n. 7
0
/*
 * Process a SPANS ARP aging timer tick
 * 
 * This function is called every SPANSARP_AGING seconds, in order to age
 * all the arp table entries.
 *
 * Called from a critical section.
 *
 * Arguments:
 *	tip	pointer to spansarp aging timer control block
 *
 * Returns:
 *	none
 *
 */
static void
spansarp_aging(struct atm_time *tip)
{
	struct spansarp	*sap, *snext;
	struct ipvcc	*ivp, *inext;
	int		i;


	/*
	 * Schedule next timeout
	 */
	atm_timeout(&spansarp_timer, SPANSARP_AGING, spansarp_aging);

	/*
	 * Run through arp table bumping each entry's aging timer.
	 */
	for (i = 0; i < SPANSARP_HASHSIZ; i++) {
		for (sap = spansarp_arptab[i]; sap; sap = snext) {
			snext = sap->sa_next;

			/*
			 * Permanent (manually installed) entries aren't aged
			 */
			if (sap->sa_origin == SAO_PERM)
				continue;

			/*
			 * See if entry is valid and over-aged
			 */
			if ((sap->sa_flags & SAF_VALID) == 0)
				continue;
			if (++sap->sa_reftime < SPANSARP_MAXAGE)
				continue;

			/*
			 * Entry is now invalid, tell IP/ATM about it
			 */
			sap->sa_flags |= SAF_LOCKED;
			for (ivp = sap->sa_ivp; ivp; ivp = inext) {
				inext = ivp->iv_arpnext;
				(*ivp->iv_ipnif->inf_arpnotify)
						(ivp, MAP_INVALID);
			}
			sap->sa_flags &= ~(SAF_LOCKED | SAF_VALID);

			if (sap->sa_ivp != NULL) {
				/*
				 * Somebody still cares, so add the arp
				 * entry to the retry list.
				 */
				LINK2TAIL(sap, struct spansarp,
						spansarp_retry_head, sa_rnext);
				if ((spansarp_rtimer.ti_flag & TIF_QUEUED) == 0)
					atm_timeout(&spansarp_rtimer,
						SPANSARP_RETRY, spansarp_retry);

				/*
				 * Issue arp request for this address
				 */
				spansarp_request(sap);

			} else {
				/*
				 * Delete unused entry
				 */
				SPANSARP_DELETE(sap);
				atm_free((caddr_t)sap);
			}
		}
	}
}
Esempio n. 8
0
/*
 * Process an SSCOP timer tick
 * 
 * This function is called SSCOP_HZ times a second in order to update
 * all of the sscop connection timers.  The sscop expiration function
 * will be called to process all timer expirations.
 *
 * Called at splnet.
 *
 * Arguments:
 *	tip	pointer to sscop timer control block
 *
 * Returns:
 *	none
 *
 */
void
sscop_timeout(struct atm_time *tip)
{
	struct sscop	*sop, **sprev;
	int		i;


	/*
	 * Schedule next timeout
	 */
	atm_timeout(&sscop_timer, ATM_HZ/SSCOP_HZ, sscop_timeout);

	/*
	 * Run through all connections, updating each active timer.
	 * If an expired timer is found, notify that entry.
	 */
	sprev = &sscop_head;
	while ((sop = *sprev) != NULL) {

		/*
		 * Check out each timer
		 */
		for (i =0; i < SSCOP_T_NUM; i++) {

			/*
			 * Decrement timer if it's active
			 */
			if (sop->so_timer[i] && (--sop->so_timer[i] == 0)) {

#ifdef DIAGNOSTIC
				{
					static char	*tn[] = {
						"POLL",
						"NORESPONSE",
						"CC",
						"IDLE"
					};
					ATM_DEBUG3("sscop_timer: %s expired, sop=%p, state=%d\n",
						tn[i], sop, sop->so_state);
				}
#endif

				/*
				 * Expired timer - process it
				 */
				(*sscop_expired[i])(sop);

				/*
				 * Make sure connection still exists
				 */
				if (*sprev != sop)
					break;
			}
		}

		/*
		 * Update previous pointer if current control
		 * block wasn't deleted
		 */
		if (*sprev == sop)
			sprev = &sop->so_next;
	}
}
Esempio n. 9
0
/*
 * Storage Pool Compaction
 * 
 * Called periodically in order to perform compaction of the
 * storage pools.  Each pool will be checked to see if any chunks 
 * can be freed, taking some care to avoid freeing too many chunks
 * in order to avoid memory thrashing.
 *
 * Called from a critical section.
 *
 * Arguments:
 *	tip	pointer to timer control block (atm_compactimer)
 *
 * Returns:
 *	none
 *
 */
static void
atm_compact(struct atm_time *tip)
{
	struct sp_info	*sip;
	struct sp_chunk	*scp;
	int		i;
	struct sp_chunk	*scp_prev;

	/*
	 * Check out all storage pools
	 */
	for (sip = atm_pool_head; sip; sip = sip->si_next) {

		/*
		 * Always keep a minimum number of chunks around
		 */
		if (sip->si_chunks <= SPOOL_MIN_CHUNK)
			continue;

		/*
		 * Maximum chunks to free at one time will leave
		 * pool with at least 50% utilization, but never
		 * go below minimum chunk count.
		 */
		i = ((sip->si_free * 2) - sip->si_total) / sip->si_blkcnt;
		i = MIN(i, sip->si_chunks - SPOOL_MIN_CHUNK);

		/*
		 * Look for chunks to free
		 */
		scp_prev = NULL;
		for (scp = sip->si_poolh; scp && i > 0; ) {

			if (scp->sc_used == 0) {

				/*
				 * Found a chunk to free, so do it
				 */
				if (scp_prev) {
					scp_prev->sc_next = scp->sc_next;
					if (sip->si_poolt == scp)
						sip->si_poolt = scp_prev;
				} else
					sip->si_poolh = scp->sc_next;

				KM_FREE((caddr_t)scp, sip->si_chunksiz,
					M_DEVBUF);

				/*
				 * Update pool controls
				 */
				sip->si_chunks--;
				sip->si_total -= sip->si_blkcnt;
				sip->si_free -= sip->si_blkcnt;
				i--;
				if (scp_prev)
					scp = scp_prev->sc_next;
				else
					scp = sip->si_poolh;
			} else {
				scp_prev = scp;
				scp = scp->sc_next;
			}
		}
	}

	/*
	 * Restart the compaction timer
	 */
	atm_timeout(&atm_compactimer, SPOOL_COMPACT, atm_compact);

	return;
}