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 $
34 * IP VCC event handler
38 #include <netatm/kern_include.h>
40 #include <netatm/ipatm/ipatm.h>
41 #include <netatm/ipatm/ipatm_var.h>
42 #include <netatm/ipatm/ipatm_serv.h>
45 __RCSID("@(#) $FreeBSD: src/sys/netatm/ipatm/ipatm_event.c,v 1.4 1999/08/28 00:48:43 peter Exp $");
50 * Process an IP VCC timeout
52 * Called when a previously scheduled ipvcc control block timer expires.
53 * Processing will be based on the current ipvcc state.
58 * tip pointer to ipvcc timer control block
71 * Back-off to ipvcc control block
73 ivp = (struct ipvcc *)
74 ((caddr_t)tip - (int)(&((struct ipvcc *)0)->iv_time));
77 * Process timeout based on protocol state
79 switch (ivp->iv_state) {
83 * Give up waiting for arp response
85 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
91 * Give up waiting for signalling manager response
93 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
98 * Try again to get an ARP entry
100 switch ((*ivp->iv_ipnif->inf_serv->is_arp_pvcopen)(ivp)) {
106 ivp->iv_state = IPVCC_ACTIVE;
111 * We've got our answer already
113 ivp->iv_state = IPVCC_ACTIVE;
114 ivp->iv_flags |= IVF_MAPOK;
115 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
122 IPVCC_TIMER(ivp, 5 * ATM_HZ);
126 panic("ipatm_timeout: invalid am_pvcopen return");
131 log(LOG_ERR, "ipatm: invalid timer state: ivp=%p, state=%d\n",
138 * Process IP VCC Connected Notification
141 * toku owner's connection token (ipvcc protocol block)
148 ipatm_connected(toku)
151 struct ipvcc *ivp = (struct ipvcc *)toku;
156 if ((ivp->iv_state != IPVCC_POPEN) &&
157 (ivp->iv_state != IPVCC_PACCEPT)) {
158 log(LOG_ERR, "ipatm: invalid CALL_CONNECTED state=%d\n",
164 * Verify possible negotiated parameter values
166 if (ivp->iv_state == IPVCC_POPEN) {
167 Atm_attributes *ap = &ivp->iv_conn->co_connvc->cvc_attr;
168 int mtu = (ivp->iv_flags & IVF_LLC) ?
169 ATM_NIF_MTU + IPATM_LLC_LEN :
175 if (ap->aal.type == ATM_AAL5) {
176 if ((ap->aal.v.aal5.forward_max_SDU_size < mtu) ||
177 (ap->aal.v.aal5.backward_max_SDU_size > mtu)) {
178 (void) ipatm_closevc(ivp,
179 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
183 if ((ap->aal.v.aal4.forward_max_SDU_size < mtu) ||
184 (ap->aal.v.aal4.backward_max_SDU_size > mtu)) {
185 (void) ipatm_closevc(ivp,
186 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
193 * Finish up VCC activation
200 * Process IP VCC Cleared Notification
203 * toku owner's connection token (ipvcc protocol block)
204 * cause pointer to cause code
211 ipatm_cleared(toku, cause)
213 struct t_atm_cause *cause;
215 struct ipvcc *ivp = (struct ipvcc *)toku;
219 * VCC has been cleared, so figure out what's next
223 switch (ivp->iv_state) {
227 * Call setup failed, see if there is another
228 * set of vcc parameters to try
230 ivp->iv_state = IPVCC_CLOSED;
231 if (ipatm_retrysvc(ivp)) {
232 (void) ipatm_closevc(ivp, cause->cause_value);
239 ivp->iv_state = IPVCC_CLOSED;
240 (void) ipatm_closevc(ivp, cause->cause_value);
247 * Process an ARP Event Notification
250 * ivp pointer to IP VCC control block
251 * event ARP event type
258 ipatm_arpnotify(ivp, event)
262 struct sockaddr_in sin;
271 switch (ivp->iv_state) {
275 * We've got our destination, however, first we'll
276 * check to make sure no other VCC to our destination
277 * has also had it's ARP table entry completed.
278 * If we don't find a better VCC to use, then we'll
279 * go ahead and open this SVC.
281 sin.sin_family = AF_INET;
282 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
283 if (ipatm_iptovc(&sin, ivp->iv_ipnif->inf_nif) != ivp) {
285 * We found a better VCC, so use it and
286 * get rid of this VCC
289 ifp = (struct ifnet *)
290 ivp->iv_ipnif->inf_nif;
291 (void) ipatm_ifoutput(ifp,
293 (struct sockaddr *)&sin);
294 ivp->iv_queue = NULL;
296 (void) ipatm_closevc(ivp,
297 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
301 * We like this VCC...
303 ivp->iv_flags |= IVF_MAPOK;
304 if (ipatm_opensvc(ivp)) {
305 (void) ipatm_closevc(ivp,
306 T_ATM_CAUSE_TEMPORARY_FAILURE);
315 * Everything looks good, so accept new mapping
317 ivp->iv_flags |= IVF_MAPOK;
318 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
323 if ((ivp->iv_state == IPVCC_ACTIVE) && ivp->iv_queue) {
324 sin.sin_family = AF_INET;
325 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
326 ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
327 (void) ipatm_ifoutput(ifp, ivp->iv_queue,
328 (struct sockaddr *)&sin);
329 ivp->iv_queue = NULL;
336 switch (ivp->iv_state) {
343 * Mapping has gone stale, so we cant use this VCC
344 * until the mapping is refreshed
346 ivp->iv_flags &= ~IVF_MAPOK;
353 * ARP lookup failed, just trash it all
355 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
360 * ARP mapping has changed
362 if (ivp->iv_flags & IVF_PVC) {
364 * For PVCs, just reset lookup cache if needed
366 if (last_map_ipvcc == ivp) {
368 last_map_ipvcc = NULL;
372 * Close SVC if it has already used this mapping
374 switch (ivp->iv_state) {
378 (void) ipatm_closevc(ivp,
379 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
386 log(LOG_ERR, "ipatm: unknown arp event %d, ivp=%p\n",
393 * Process an IP VCC idle timer tick
395 * This function is called every IPATM_IDLE_TIME seconds, in order to
396 * scan for idle IP VCC's. If an active VCC reaches the idle time limit,
397 * then it will be closed.
402 * tip pointer to the VCC idle timer control block
410 struct atm_time *tip;
412 struct ipvcc *ivp, *inext;
417 * Schedule next timeout
419 atm_timeout(&ipatm_itimer, IPATM_IDLE_TIME, ipatm_itimeout);
422 * Check for disabled idle timeout
424 if (ipatm_vcidle == 0)
428 * Check out all IP VCCs
430 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
431 for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
434 inext = Q_NEXT(ivp, struct ipvcc, iv_elem);
437 * Looking for active, idle SVCs
439 if (ivp->iv_flags & (IVF_PVC | IVF_NOIDLE))
441 if (ivp->iv_state != IPVCC_ACTIVE)
443 if (++ivp->iv_idle < ipatm_vcidle)
447 * OK, we found one - close the VCC
449 (void) ipatm_closevc(ivp,
450 T_ATM_CAUSE_UNSPECIFIED_NORMAL);