3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/ipatm/ipatm_event.c,v 1.4 1999/08/28 00:48:43 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_event.c,v 1.3 2003/08/07 21:17:34 dillon Exp $
34 * IP VCC event handler
38 #include <netatm/kern_include.h>
41 #include "ipatm_var.h"
42 #include "ipatm_serv.h"
45 * Process an IP VCC timeout
47 * Called when a previously scheduled ipvcc control block timer expires.
48 * Processing will be based on the current ipvcc state.
53 * tip pointer to ipvcc timer control block
66 * Back-off to ipvcc control block
68 ivp = (struct ipvcc *)
69 ((caddr_t)tip - (int)(&((struct ipvcc *)0)->iv_time));
72 * Process timeout based on protocol state
74 switch (ivp->iv_state) {
78 * Give up waiting for arp response
80 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
86 * Give up waiting for signalling manager response
88 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
93 * Try again to get an ARP entry
95 switch ((*ivp->iv_ipnif->inf_serv->is_arp_pvcopen)(ivp)) {
101 ivp->iv_state = IPVCC_ACTIVE;
106 * We've got our answer already
108 ivp->iv_state = IPVCC_ACTIVE;
109 ivp->iv_flags |= IVF_MAPOK;
110 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
117 IPVCC_TIMER(ivp, 5 * ATM_HZ);
121 panic("ipatm_timeout: invalid am_pvcopen return");
126 log(LOG_ERR, "ipatm: invalid timer state: ivp=%p, state=%d\n",
133 * Process IP VCC Connected Notification
136 * toku owner's connection token (ipvcc protocol block)
143 ipatm_connected(toku)
146 struct ipvcc *ivp = (struct ipvcc *)toku;
151 if ((ivp->iv_state != IPVCC_POPEN) &&
152 (ivp->iv_state != IPVCC_PACCEPT)) {
153 log(LOG_ERR, "ipatm: invalid CALL_CONNECTED state=%d\n",
159 * Verify possible negotiated parameter values
161 if (ivp->iv_state == IPVCC_POPEN) {
162 Atm_attributes *ap = &ivp->iv_conn->co_connvc->cvc_attr;
163 int mtu = (ivp->iv_flags & IVF_LLC) ?
164 ATM_NIF_MTU + IPATM_LLC_LEN :
170 if (ap->aal.type == ATM_AAL5) {
171 if ((ap->aal.v.aal5.forward_max_SDU_size < mtu) ||
172 (ap->aal.v.aal5.backward_max_SDU_size > mtu)) {
173 (void) ipatm_closevc(ivp,
174 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
178 if ((ap->aal.v.aal4.forward_max_SDU_size < mtu) ||
179 (ap->aal.v.aal4.backward_max_SDU_size > mtu)) {
180 (void) ipatm_closevc(ivp,
181 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
188 * Finish up VCC activation
195 * Process IP VCC Cleared Notification
198 * toku owner's connection token (ipvcc protocol block)
199 * cause pointer to cause code
206 ipatm_cleared(toku, cause)
208 struct t_atm_cause *cause;
210 struct ipvcc *ivp = (struct ipvcc *)toku;
214 * VCC has been cleared, so figure out what's next
218 switch (ivp->iv_state) {
222 * Call setup failed, see if there is another
223 * set of vcc parameters to try
225 ivp->iv_state = IPVCC_CLOSED;
226 if (ipatm_retrysvc(ivp)) {
227 (void) ipatm_closevc(ivp, cause->cause_value);
234 ivp->iv_state = IPVCC_CLOSED;
235 (void) ipatm_closevc(ivp, cause->cause_value);
242 * Process an ARP Event Notification
245 * ivp pointer to IP VCC control block
246 * event ARP event type
253 ipatm_arpnotify(ivp, event)
257 struct sockaddr_in sin;
266 switch (ivp->iv_state) {
270 * We've got our destination, however, first we'll
271 * check to make sure no other VCC to our destination
272 * has also had it's ARP table entry completed.
273 * If we don't find a better VCC to use, then we'll
274 * go ahead and open this SVC.
276 sin.sin_family = AF_INET;
277 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
278 if (ipatm_iptovc(&sin, ivp->iv_ipnif->inf_nif) != ivp) {
280 * We found a better VCC, so use it and
281 * get rid of this VCC
284 ifp = (struct ifnet *)
285 ivp->iv_ipnif->inf_nif;
286 (void) ipatm_ifoutput(ifp,
288 (struct sockaddr *)&sin);
289 ivp->iv_queue = NULL;
291 (void) ipatm_closevc(ivp,
292 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
296 * We like this VCC...
298 ivp->iv_flags |= IVF_MAPOK;
299 if (ipatm_opensvc(ivp)) {
300 (void) ipatm_closevc(ivp,
301 T_ATM_CAUSE_TEMPORARY_FAILURE);
310 * Everything looks good, so accept new mapping
312 ivp->iv_flags |= IVF_MAPOK;
313 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
318 if ((ivp->iv_state == IPVCC_ACTIVE) && ivp->iv_queue) {
319 sin.sin_family = AF_INET;
320 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
321 ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
322 (void) ipatm_ifoutput(ifp, ivp->iv_queue,
323 (struct sockaddr *)&sin);
324 ivp->iv_queue = NULL;
331 switch (ivp->iv_state) {
338 * Mapping has gone stale, so we cant use this VCC
339 * until the mapping is refreshed
341 ivp->iv_flags &= ~IVF_MAPOK;
348 * ARP lookup failed, just trash it all
350 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
355 * ARP mapping has changed
357 if (ivp->iv_flags & IVF_PVC) {
359 * For PVCs, just reset lookup cache if needed
361 if (last_map_ipvcc == ivp) {
363 last_map_ipvcc = NULL;
367 * Close SVC if it has already used this mapping
369 switch (ivp->iv_state) {
373 (void) ipatm_closevc(ivp,
374 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
381 log(LOG_ERR, "ipatm: unknown arp event %d, ivp=%p\n",
388 * Process an IP VCC idle timer tick
390 * This function is called every IPATM_IDLE_TIME seconds, in order to
391 * scan for idle IP VCC's. If an active VCC reaches the idle time limit,
392 * then it will be closed.
397 * tip pointer to the VCC idle timer control block
405 struct atm_time *tip;
407 struct ipvcc *ivp, *inext;
412 * Schedule next timeout
414 atm_timeout(&ipatm_itimer, IPATM_IDLE_TIME, ipatm_itimeout);
417 * Check for disabled idle timeout
419 if (ipatm_vcidle == 0)
423 * Check out all IP VCCs
425 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
426 for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
429 inext = Q_NEXT(ivp, struct ipvcc, iv_elem);
432 * Looking for active, idle SVCs
434 if (ivp->iv_flags & (IVF_PVC | IVF_NOIDLE))
436 if (ivp->iv_state != IPVCC_ACTIVE)
438 if (++ivp->iv_idle < ipatm_vcidle)
442 * OK, we found one - close the VCC
444 (void) ipatm_closevc(ivp,
445 T_ATM_CAUSE_UNSPECIFIED_NORMAL);