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
);