fetch.9: Minor fixes.
[dragonfly.git] / sys / netproto / atm / ipatm / ipatm_event.c
blob5fae09b1add16b1f50a5ef7544b810f38387d920
1 /*
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 $
31 * IP Over ATM Support
32 * -------------------
34 * IP VCC event handler
38 #include <netproto/atm/kern_include.h>
40 #include "ipatm.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.
50 * Called at splnet.
52 * Arguments:
53 * tip pointer to ipvcc timer control block
55 * Returns:
56 * none
59 void
60 ipatm_timeout(struct atm_time *tip)
62 struct ipvcc *ivp;
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) {
75 case IPVCC_PMAP:
77 * Give up waiting for arp response
79 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
80 break;
82 case IPVCC_POPEN:
83 case IPVCC_PACCEPT:
85 * Give up waiting for signalling manager response
87 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
88 break;
90 case IPVCC_ACTPENT:
92 * Try again to get an ARP entry
94 switch ((*ivp->iv_ipnif->inf_serv->is_arp_pvcopen)(ivp)) {
96 case MAP_PROCEEDING:
98 * Wait for answer
100 ivp->iv_state = IPVCC_ACTIVE;
101 break;
103 case MAP_VALID:
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;
110 break;
112 case MAP_FAILED:
114 * Try again later
116 IPVCC_TIMER(ivp, 5 * ATM_HZ);
117 break;
119 default:
120 panic("ipatm_timeout: invalid am_pvcopen return");
122 break;
124 default:
125 log(LOG_ERR, "ipatm: invalid timer state: ivp=%p, state=%d\n",
126 ivp, ivp->iv_state);
132 * Process IP VCC Connected Notification
134 * Arguments:
135 * toku owner's connection token (ipvcc protocol block)
137 * Returns:
138 * none
141 void
142 ipatm_connected(void *toku)
144 struct ipvcc *ivp = (struct ipvcc *)toku;
147 * SVC is connected
149 if ((ivp->iv_state != IPVCC_POPEN) &&
150 (ivp->iv_state != IPVCC_PACCEPT)) {
151 log(LOG_ERR, "ipatm: invalid CALL_CONNECTED state=%d\n",
152 ivp->iv_state);
153 return;
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 :
163 ATM_NIF_MTU;
166 * Verify final MTU
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)) {
171 ipatm_closevc(ivp,
172 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
173 return;
175 } else {
176 if ((ap->aal.v.aal4.forward_max_SDU_size < mtu) ||
177 (ap->aal.v.aal4.backward_max_SDU_size > mtu)) {
178 ipatm_closevc(ivp,
179 T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED);
180 return;
186 * Finish up VCC activation
188 ipatm_activate(ivp);
193 * Process IP VCC Cleared Notification
195 * Arguments:
196 * toku owner's connection token (ipvcc protocol block)
197 * cause pointer to cause code
199 * Returns:
200 * none
203 void
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
212 ivp->iv_conn = NULL;
214 switch (ivp->iv_state) {
216 case IPVCC_POPEN:
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);
225 break;
227 case IPVCC_PACCEPT:
228 case IPVCC_ACTPENT:
229 case IPVCC_ACTIVE:
230 ivp->iv_state = IPVCC_CLOSED;
231 ipatm_closevc(ivp, cause->cause_value);
232 break;
238 * Process an ARP Event Notification
240 * Arguments:
241 * ivp pointer to IP VCC control block
242 * event ARP event type
244 * Returns:
245 * none
248 void
249 ipatm_arpnotify(struct ipvcc *ivp, int event)
251 struct sockaddr_in sin;
252 struct ifnet *ifp;
255 * Process event
257 switch (event) {
259 case MAP_VALID:
260 switch (ivp->iv_state) {
262 case IPVCC_PMAP:
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
277 if (ivp->iv_queue) {
278 ifp = (struct ifnet *)
279 ivp->iv_ipnif->inf_nif;
280 ipatm_ifoutput(ifp,
281 ivp->iv_queue,
282 (struct sockaddr *)&sin);
283 ivp->iv_queue = NULL;
285 ipatm_closevc(ivp,
286 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
288 } else {
290 * We like this VCC...
292 ivp->iv_flags |= IVF_MAPOK;
293 if (ipatm_opensvc(ivp)) {
294 ipatm_closevc(ivp,
295 T_ATM_CAUSE_TEMPORARY_FAILURE);
298 break;
300 case IPVCC_POPEN:
301 case IPVCC_PACCEPT:
302 case IPVCC_ACTIVE:
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;
310 * Send queued packet
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;
320 break;
322 break;
324 case MAP_INVALID:
325 switch (ivp->iv_state) {
327 case IPVCC_POPEN:
328 case IPVCC_PACCEPT:
329 case IPVCC_ACTIVE:
332 * Mapping has gone stale, so we cant use this VCC
333 * until the mapping is refreshed
335 ivp->iv_flags &= ~IVF_MAPOK;
336 break;
338 break;
340 case MAP_FAILED:
342 * ARP lookup failed, just trash it all
344 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
345 break;
347 case MAP_CHANGED:
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) {
356 last_map_ipdst = 0;
357 last_map_ipvcc = NULL;
359 } else {
361 * Close SVC if it has already used this mapping
363 switch (ivp->iv_state) {
365 case IPVCC_POPEN:
366 case IPVCC_ACTIVE:
367 ipatm_closevc(ivp,
368 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
369 break;
372 break;
374 default:
375 log(LOG_ERR, "ipatm: unknown arp event %d, ivp=%p\n",
376 event, ivp);
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.
388 * Called at splnet.
390 * Arguments:
391 * tip pointer to the VCC idle timer control block
393 * Returns:
394 * none
397 void
398 ipatm_itimeout(struct atm_time *tip)
400 struct ipvcc *ivp, *inext;
401 struct ip_nif *inp;
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)
413 return;
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;
420 ivp = inext) {
422 inext = Q_NEXT(ivp, struct ipvcc, iv_elem);
425 * Looking for active, idle SVCs
427 if (ivp->iv_flags & (IVF_PVC | IVF_NOIDLE))
428 continue;
429 if (ivp->iv_state != IPVCC_ACTIVE)
430 continue;
431 if (++ivp->iv_idle < ipatm_vcidle)
432 continue;
435 * OK, we found one - close the VCC
437 ipatm_closevc(ivp,
438 T_ATM_CAUSE_UNSPECIFIED_NORMAL);