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 $
33 * IP VCC event handler
37 #include <netproto/atm/kern_include.h>
40 #include "ipatm_var.h"
41 #include "ipatm_serv.h"
44 * Process an IP VCC timeout
46 * Called when a previously scheduled ipvcc control block timer expires.
47 * Processing will be based on the current ipvcc state.
52 * tip pointer to ipvcc timer control block
59 ipatm_timeout(struct atm_time *tip)
64 * Back-off to ipvcc control block
66 ivp = (struct ipvcc *)
67 ((caddr_t)tip - __offsetof(struct ipvcc, iv_time));
70 * Process timeout based on protocol state
72 switch (ivp->iv_state) {
76 * Give up waiting for arp response
78 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
84 * Give up waiting for signalling manager response
86 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
91 * Try again to get an ARP entry
93 switch ((*ivp->iv_ipnif->inf_serv->is_arp_pvcopen)(ivp)) {
99 ivp->iv_state = IPVCC_ACTIVE;
104 * We've got our answer already
106 ivp->iv_state = IPVCC_ACTIVE;
107 ivp->iv_flags |= IVF_MAPOK;
108 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
115 IPVCC_TIMER(ivp, 5 * ATM_HZ);
119 panic("ipatm_timeout: invalid am_pvcopen return");
124 log(LOG_ERR, "ipatm: invalid timer state: ivp=%p, state=%d\n",
131 * Process IP VCC Connected Notification
134 * toku owner's connection token (ipvcc protocol block)
141 ipatm_connected(void *toku)
143 struct ipvcc *ivp = (struct ipvcc *)toku;
148 if ((ivp->iv_state != IPVCC_POPEN) &&
149 (ivp->iv_state != IPVCC_PACCEPT)) {
150 log(LOG_ERR, "ipatm: invalid CALL_CONNECTED state=%d\n",
156 * Verify possible negotiated parameter values
158 if (ivp->iv_state == IPVCC_POPEN) {
159 Atm_attributes *ap = &ivp->iv_conn->co_connvc->cvc_attr;
160 int mtu = (ivp->iv_flags & IVF_LLC) ?
161 ATM_NIF_MTU + IPATM_LLC_LEN :
167 if (ap->aal.type == ATM_AAL5) {
168 if ((ap->aal.v.aal5.forward_max_SDU_size < mtu) ||
169 (ap->aal.v.aal5.backward_max_SDU_size > mtu)) {
171 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
175 if ((ap->aal.v.aal4.forward_max_SDU_size < mtu) ||
176 (ap->aal.v.aal4.backward_max_SDU_size > mtu)) {
178 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
185 * Finish up VCC activation
192 * Process IP VCC Cleared Notification
195 * toku owner's connection token (ipvcc protocol block)
196 * cause pointer to cause code
203 ipatm_cleared(void *toku, struct t_atm_cause *cause)
205 struct ipvcc *ivp = (struct ipvcc *)toku;
209 * VCC has been cleared, so figure out what's next
213 switch (ivp->iv_state) {
217 * Call setup failed, see if there is another
218 * set of vcc parameters to try
220 ivp->iv_state = IPVCC_CLOSED;
221 if (ipatm_retrysvc(ivp)) {
222 ipatm_closevc(ivp, cause->cause_value);
229 ivp->iv_state = IPVCC_CLOSED;
230 ipatm_closevc(ivp, cause->cause_value);
237 * Process an ARP Event Notification
240 * ivp pointer to IP VCC control block
241 * event ARP event type
248 ipatm_arpnotify(struct ipvcc *ivp, int event)
250 struct sockaddr_in sin;
259 switch (ivp->iv_state) {
263 * We've got our destination, however, first we'll
264 * check to make sure no other VCC to our destination
265 * has also had it's ARP table entry completed.
266 * If we don't find a better VCC to use, then we'll
267 * go ahead and open this SVC.
269 sin.sin_family = AF_INET;
270 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
271 if (ipatm_iptovc(&sin, ivp->iv_ipnif->inf_nif) != ivp) {
273 * We found a better VCC, so use it and
274 * get rid of this VCC
277 ifp = (struct ifnet *)
278 ivp->iv_ipnif->inf_nif;
281 (struct sockaddr *)&sin);
282 ivp->iv_queue = NULL;
285 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
289 * We like this VCC...
291 ivp->iv_flags |= IVF_MAPOK;
292 if (ipatm_opensvc(ivp)) {
294 T_ATM_CAUSE_TEMPORARY_FAILURE);
303 * Everything looks good, so accept new mapping
305 ivp->iv_flags |= IVF_MAPOK;
306 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
311 if ((ivp->iv_state == IPVCC_ACTIVE) && ivp->iv_queue) {
312 sin.sin_family = AF_INET;
313 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
314 ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
315 ipatm_ifoutput(ifp, ivp->iv_queue,
316 (struct sockaddr *)&sin);
317 ivp->iv_queue = NULL;
324 switch (ivp->iv_state) {
331 * Mapping has gone stale, so we cant use this VCC
332 * until the mapping is refreshed
334 ivp->iv_flags &= ~IVF_MAPOK;
341 * ARP lookup failed, just trash it all
343 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
348 * ARP mapping has changed
350 if (ivp->iv_flags & IVF_PVC) {
352 * For PVCs, just reset lookup cache if needed
354 if (last_map_ipvcc == ivp) {
356 last_map_ipvcc = NULL;
360 * Close SVC if it has already used this mapping
362 switch (ivp->iv_state) {
367 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
374 log(LOG_ERR, "ipatm: unknown arp event %d, ivp=%p\n",
381 * Process an IP VCC idle timer tick
383 * This function is called every IPATM_IDLE_TIME seconds, in order to
384 * scan for idle IP VCC's. If an active VCC reaches the idle time limit,
385 * then it will be closed.
390 * tip pointer to the VCC idle timer control block
397 ipatm_itimeout(struct atm_time *tip)
399 struct ipvcc *ivp, *inext;
404 * Schedule next timeout
406 atm_timeout(&ipatm_itimer, IPATM_IDLE_TIME, ipatm_itimeout);
409 * Check for disabled idle timeout
411 if (ipatm_vcidle == 0)
415 * Check out all IP VCCs
417 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
418 for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
421 inext = Q_NEXT(ivp, struct ipvcc, iv_elem);
424 * Looking for active, idle SVCs
426 if (ivp->iv_flags & (IVF_PVC | IVF_NOIDLE))
428 if (ivp->iv_state != IPVCC_ACTIVE)
430 if (++ivp->iv_idle < ipatm_vcidle)
434 * OK, we found one - close the VCC
437 T_ATM_CAUSE_UNSPECIFIED_NORMAL);