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.5 2006/01/14 13:36:39 swildner Exp $
34 * IP VCC event handler
38 #include <netproto/atm/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
60 ipatm_timeout(struct atm_time *tip)
65 * Back-off to ipvcc control block
67 ivp = (struct ipvcc *)
68 ((caddr_t)tip - (int)(&((struct ipvcc *)0)->iv_time));
71 * Process timeout based on protocol state
73 switch (ivp->iv_state) {
77 * Give up waiting for arp response
79 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
85 * Give up waiting for signalling manager response
87 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
92 * Try again to get an ARP entry
94 switch ((*ivp->iv_ipnif->inf_serv->is_arp_pvcopen)(ivp)) {
100 ivp->iv_state = IPVCC_ACTIVE;
105 * We've got our answer already
107 ivp->iv_state = IPVCC_ACTIVE;
108 ivp->iv_flags |= IVF_MAPOK;
109 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
116 IPVCC_TIMER(ivp, 5 * ATM_HZ);
120 panic("ipatm_timeout: invalid am_pvcopen return");
125 log(LOG_ERR, "ipatm: invalid timer state: ivp=%p, state=%d\n",
132 * Process IP VCC Connected Notification
135 * toku owner's connection token (ipvcc protocol block)
142 ipatm_connected(void *toku)
144 struct ipvcc *ivp = (struct ipvcc *)toku;
149 if ((ivp->iv_state != IPVCC_POPEN) &&
150 (ivp->iv_state != IPVCC_PACCEPT)) {
151 log(LOG_ERR, "ipatm: invalid CALL_CONNECTED state=%d\n",
157 * Verify possible negotiated parameter values
159 if (ivp->iv_state == IPVCC_POPEN) {
160 Atm_attributes *ap = &ivp->iv_conn->co_connvc->cvc_attr;
161 int mtu = (ivp->iv_flags & IVF_LLC) ?
162 ATM_NIF_MTU + IPATM_LLC_LEN :
168 if (ap->aal.type == ATM_AAL5) {
169 if ((ap->aal.v.aal5.forward_max_SDU_size < mtu) ||
170 (ap->aal.v.aal5.backward_max_SDU_size > mtu)) {
172 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
176 if ((ap->aal.v.aal4.forward_max_SDU_size < mtu) ||
177 (ap->aal.v.aal4.backward_max_SDU_size > mtu)) {
179 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
186 * Finish up VCC activation
193 * Process IP VCC Cleared Notification
196 * toku owner's connection token (ipvcc protocol block)
197 * cause pointer to cause code
204 ipatm_cleared(void *toku, struct t_atm_cause *cause)
206 struct ipvcc *ivp = (struct ipvcc *)toku;
210 * VCC has been cleared, so figure out what's next
214 switch (ivp->iv_state) {
218 * Call setup failed, see if there is another
219 * set of vcc parameters to try
221 ivp->iv_state = IPVCC_CLOSED;
222 if (ipatm_retrysvc(ivp)) {
223 ipatm_closevc(ivp, cause->cause_value);
230 ivp->iv_state = IPVCC_CLOSED;
231 ipatm_closevc(ivp, cause->cause_value);
238 * Process an ARP Event Notification
241 * ivp pointer to IP VCC control block
242 * event ARP event type
249 ipatm_arpnotify(struct ipvcc *ivp, int event)
251 struct sockaddr_in sin;
260 switch (ivp->iv_state) {
264 * We've got our destination, however, first we'll
265 * check to make sure no other VCC to our destination
266 * has also had it's ARP table entry completed.
267 * If we don't find a better VCC to use, then we'll
268 * go ahead and open this SVC.
270 sin.sin_family = AF_INET;
271 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
272 if (ipatm_iptovc(&sin, ivp->iv_ipnif->inf_nif) != ivp) {
274 * We found a better VCC, so use it and
275 * get rid of this VCC
278 ifp = (struct ifnet *)
279 ivp->iv_ipnif->inf_nif;
282 (struct sockaddr *)&sin);
283 ivp->iv_queue = NULL;
286 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
290 * We like this VCC...
292 ivp->iv_flags |= IVF_MAPOK;
293 if (ipatm_opensvc(ivp)) {
295 T_ATM_CAUSE_TEMPORARY_FAILURE);
304 * Everything looks good, so accept new mapping
306 ivp->iv_flags |= IVF_MAPOK;
307 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
312 if ((ivp->iv_state == IPVCC_ACTIVE) && ivp->iv_queue) {
313 sin.sin_family = AF_INET;
314 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
315 ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
316 ipatm_ifoutput(ifp, ivp->iv_queue,
317 (struct sockaddr *)&sin);
318 ivp->iv_queue = NULL;
325 switch (ivp->iv_state) {
332 * Mapping has gone stale, so we cant use this VCC
333 * until the mapping is refreshed
335 ivp->iv_flags &= ~IVF_MAPOK;
342 * ARP lookup failed, just trash it all
344 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
349 * ARP mapping has changed
351 if (ivp->iv_flags & IVF_PVC) {
353 * For PVCs, just reset lookup cache if needed
355 if (last_map_ipvcc == ivp) {
357 last_map_ipvcc = NULL;
361 * Close SVC if it has already used this mapping
363 switch (ivp->iv_state) {
368 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
375 log(LOG_ERR, "ipatm: unknown arp event %d, ivp=%p\n",
382 * Process an IP VCC idle timer tick
384 * This function is called every IPATM_IDLE_TIME seconds, in order to
385 * scan for idle IP VCC's. If an active VCC reaches the idle time limit,
386 * then it will be closed.
391 * tip pointer to the VCC idle timer control block
398 ipatm_itimeout(struct atm_time *tip)
400 struct ipvcc *ivp, *inext;
405 * Schedule next timeout
407 atm_timeout(&ipatm_itimer, IPATM_IDLE_TIME, ipatm_itimeout);
410 * Check for disabled idle timeout
412 if (ipatm_vcidle == 0)
416 * Check out all IP VCCs
418 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
419 for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
422 inext = Q_NEXT(ivp, struct ipvcc, iv_elem);
425 * Looking for active, idle SVCs
427 if (ivp->iv_flags & (IVF_PVC | IVF_NOIDLE))
429 if (ivp->iv_state != IPVCC_ACTIVE)
431 if (++ivp->iv_idle < ipatm_vcidle)
435 * OK, we found one - close the VCC
438 T_ATM_CAUSE_UNSPECIFIED_NORMAL);