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_vcm.c,v 1.4 1999/08/28 00:48:45 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_vcm.c,v 1.8 2006/01/14 13:36:39 swildner Exp $
34 * Virtual Channel Manager
38 #include <netproto/atm/kern_include.h>
41 #include "ipatm_var.h"
42 #include "ipatm_serv.h"
44 Atm_attributes ipatm_aal5llc = {
120 T_ATM_NETWORK_CODING,
137 Atm_attributes ipatm_aal5null = {
139 CMAPI_CPCS, /* api */
141 sizeof(struct ifnet *), /* headin */
200 T_ATM_NETWORK_CODING,
217 Atm_attributes ipatm_aal4null = {
219 CMAPI_CPCS, /* api */
221 sizeof(struct ifnet *), /* headin */
280 T_ATM_NETWORK_CODING,
297 static struct t_atm_cause ipatm_cause = {
308 * This function will perform all actions necessary to activate a
309 * PVC for IP usage. In particular, it will allocate control blocks,
310 * open the PVC, initialize PVC stack, and initiate whatever ARP
311 * procedures are required.
314 * pvp pointer to PVC parameter structure
315 * sivp address to return pointer to IP PVC control block
318 * 0 PVC was successfully opened
319 * errno open failed - reason indicated
323 ipatm_openpvc(struct ipatmpvc *pvp, struct ipvcc **sivp)
332 inp = pvp->ipp_ipnif;
336 * Make sure interface is ready to go
338 if (inp->inf_state != IPNIF_ACTIVE) {
344 * Validate fixed destination IP address
346 if (pvp->ipp_dst.sin_addr.s_addr != INADDR_ANY) {
347 if (in_broadcast(pvp->ipp_dst.sin_addr, &nip->nif_if) ||
348 IN_MULTICAST(ntohl(pvp->ipp_dst.sin_addr.s_addr)) ||
349 ipatm_chknif(pvp->ipp_dst.sin_addr, inp)) {
356 * Allocate IP VCC block
358 ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
367 ivp->iv_flags = IVF_PVC;
368 if (pvp->ipp_encaps == ATM_ENC_LLC)
369 ivp->iv_flags |= IVF_LLC;
372 * Fill out connection attributes
374 if (pvp->ipp_aal == ATM_AAL5) {
375 if (pvp->ipp_encaps == ATM_ENC_LLC)
378 ap = &ipatm_aal5null;
380 ap = &ipatm_aal4null;
384 ap->traffic.v.forward.PCR_all_traffic = nip->nif_pif->pif_pcr;
385 ap->traffic.v.backward.PCR_all_traffic = nip->nif_pif->pif_pcr;
386 ap->called.addr.address_format = T_ATM_PVC_ADDR;
387 ap->called.addr.address_length = sizeof(Atm_addr_pvc);
388 pvcp = (Atm_addr_pvc *)ap->called.addr.address;
389 ATM_PVC_SET_VPI(pvcp, pvp->ipp_vpi);
390 ATM_PVC_SET_VCI(pvcp, pvp->ipp_vci);
391 ap->called.subaddr.address_format = T_ATM_ABSENT;
392 ap->called.subaddr.address_length = 0;
397 err = atm_cm_connect(&ipatm_endpt, ivp, ap, &ivp->iv_conn);
399 atm_free((caddr_t)ivp);
404 * Save PVC information and link in VCC
406 /* ivp->iv_ = ap->headout; */
409 * Queue VCC onto its network interface
413 ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
418 * Set destination IP address and IPVCC state
420 if (pvp->ipp_dst.sin_addr.s_addr == INADDR_ANY) {
422 * Initiate ARP processing
424 switch ((*inp->inf_serv->is_arp_pvcopen)(ivp)) {
430 ivp->iv_state = IPVCC_ACTIVE;
435 * We've got our answer already
437 ivp->iv_state = IPVCC_ACTIVE;
438 ivp->iv_flags |= IVF_MAPOK;
439 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
446 ivp->iv_state = IPVCC_ACTPENT;
447 IPVCC_TIMER(ivp, 1 * ATM_HZ);
451 panic("ipatm_openpvc: invalid arp_pvcopen return");
456 * Use configured IP destination
458 ivp->iv_dst.s_addr = pvp->ipp_dst.sin_addr.s_addr;
459 ivp->iv_state = IPVCC_ACTIVE;
460 ivp->iv_flags |= IVF_MAPOK;
474 * This function will initiate the creation of an IP SVC. The IP VCC
475 * control block will be initialized and, if required, we will initiate
476 * ARP processing in order to resolve the destination's ATM address. Once
477 * the destination ATM address is known, ipatm_opensvc() will be called.
480 * ifp pointer to destination ifnet structure
481 * daf destination address family type
482 * dst pointer to destination address
483 * sivp address to return pointer to IP SVC control block
486 * 0 SVC creation was successfully initiated
487 * errno creation failed - reason indicated
491 ipatm_createsvc(struct ifnet *ifp, u_short daf, caddr_t dst,
494 struct atm_nif *nip = (struct atm_nif *)ifp;
502 * Get IP interface and make sure its ready
504 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
505 if (inp->inf_nif == nip)
512 if (inp->inf_state != IPNIF_ACTIVE) {
518 * Validate destination address
520 if (daf == AF_INET) {
522 * Destination is IP address
524 ip = (struct in_addr *)dst;
526 if (ip->s_addr == INADDR_ANY) {
530 } else if (daf == AF_ATM) {
532 * Destination is ATM address
534 atm = (Atm_addr *)dst;
536 if (atm->address_format == T_ATM_ABSENT) {
546 * Make sure we have services provider and ARP support
548 if ((inp->inf_serv == NULL) ||
549 (inp->inf_serv->is_arp_svcout == NULL)) {
557 ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
566 ivp->iv_flags = IVF_SVC;
570 * Get destination ATM address
572 if (daf == AF_INET) {
576 ivp->iv_dst.s_addr = ip->s_addr;
578 switch ((*inp->inf_serv->is_arp_svcout)(ivp, ip)) {
584 ivp->iv_state = IPVCC_PMAP;
585 IPVCC_TIMER(ivp, IPATM_ARP_TIME);
590 * We've got our answer already, so open SVC
592 ivp->iv_flags |= IVF_MAPOK;
593 err = ipatm_opensvc(ivp);
595 (*inp->inf_serv->is_arp_close)(ivp);
596 atm_free((caddr_t)ivp);
603 * So sorry...come again
605 atm_free((caddr_t)ivp);
610 panic("ipatm_createsvc: invalid arp_svcout return");
614 * We were given the ATM address, so open the SVC
616 * Create temporary arp map entry so that opensvc() works.
617 * Caller must set up a permanent entry immediately! (yuk)
621 ATM_ADDR_COPY(atm, &map.am_dstatm);
622 map.am_dstatmsub.address_format = T_ATM_ABSENT;
623 map.am_dstatmsub.address_length = 0;
624 ivp->iv_arpent = ↦
625 err = ipatm_opensvc(ivp);
627 atm_free((caddr_t)ivp);
630 ivp->iv_arpent = NULL;
634 * Queue VCC onto its network interface
638 ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
652 * This function will continue the IP SVC creation process. Here, we
653 * will issue an SVC open to the signalling manager and then wait for
654 * the final SVC setup results.
657 * ivp pointer to IP SVC to open
660 * 0 SVC open was successfully initiated
661 * errno open failed - reason indicated
665 ipatm_opensvc(struct ipvcc *ivp)
667 struct ip_nif *inp = ivp->iv_ipnif;
672 * Cancel possible arp timeout
677 * Fill out connection attributes
680 if (inp->inf_serv->is_vccparm[i].ivc_aal == ATM_AAL5) {
681 if (inp->inf_serv->is_vccparm[i].ivc_encaps == ATM_ENC_LLC) {
683 ivp->iv_flags |= IVF_LLC;
685 ap = &ipatm_aal5null;
686 ivp->iv_flags &= ~IVF_LLC;
689 ap = &ipatm_aal4null;
690 ivp->iv_flags &= ~IVF_LLC;
693 ap->nif = inp->inf_nif;
694 ap->traffic.v.forward.PCR_all_traffic = inp->inf_nif->nif_pif->pif_pcr;
695 ap->traffic.v.backward.PCR_all_traffic = inp->inf_nif->nif_pif->pif_pcr;
697 ATM_ADDR_COPY(&ivp->iv_arpent->am_dstatm, &ap->called.addr);
698 ATM_ADDR_COPY(&ivp->iv_arpent->am_dstatmsub, &ap->called.subaddr);
703 err = atm_cm_connect(&ipatm_endpt, ivp, ap, &ivp->iv_conn);
708 * Call is progressing
710 /* ivp->iv_ = ap->headout; */
713 * Now we just wait for a CALL_CONNECTED event
715 ivp->iv_state = IPVCC_POPEN;
716 IPVCC_TIMER(ivp, IPATM_SVC_TIME);
722 * We've been hooked up with a shared VCC
724 /* ivp->iv_ = ap->headout; */
734 * Retry an IP SVC Open
736 * This function will attempt to retry a failed SVC open request. The IP
737 * interface service provider specifies a list of possible VCC parameters
738 * for IP to use. We will try each set of parameters in turn until either
739 * an open succeeds or we reach the end of the list.
742 * ivp pointer to IP SVC
745 * 0 SVC (re)open was successfully initiated
750 ipatm_retrysvc(struct ipvcc *ivp)
752 struct ip_nif *inp = ivp->iv_ipnif;
755 * If there isn't another set of vcc parameters to try, return
757 if ((++ivp->iv_parmx >= IPATM_VCCPARMS) ||
758 (inp->inf_serv->is_vccparm[ivp->iv_parmx].ivc_aal == 0))
762 * Okay, now initiate open with a new set of parameters
764 return (ipatm_opensvc(ivp));
769 * Finish IP SVC Activation
772 * ivp pointer to IP SVC
779 ipatm_activate(struct ipvcc *ivp)
783 * Connection is now active
785 ivp->iv_state = IPVCC_ACTIVE;
789 * Tell ARP module that connection is active
791 if ((*ivp->iv_ipnif->inf_serv->is_arp_svcact)(ivp)) {
792 ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
797 * Send any queued packet
799 if ((ivp->iv_flags & IVF_MAPOK) && ivp->iv_queue) {
800 struct sockaddr_in sin;
803 sin.sin_family = AF_INET;
804 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
805 ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
806 ipatm_ifoutput(ifp, ivp->iv_queue,
807 (struct sockaddr *)&sin);
808 ivp->iv_queue = NULL;
814 * Process Incoming Calls
816 * This function will receive control when an incoming call has been matched
817 * to one of our registered listen parameter blocks. Assuming the call passes
818 * acceptance criteria and all required resources are available, we will
819 * create an IP SVC and notify the connection manager of our decision. We
820 * will then await notification of the final SVC setup results. If any
821 * problems are encountered, we will just tell the connection manager to
824 * Called from a critical section.
827 * tok owner's matched listening token
828 * cop pointer to incoming call's connection block
829 * ap pointer to incoming call's attributes
830 * tokp pointer to location to store our connection token
834 * errno call rejected - reason indicated
838 ipatm_incoming(void *tok, Atm_connection *cop, Atm_attributes *ap,
841 struct atm_nif *nip = ap->nif;
843 struct ipvcc *ivp = NULL;
845 int usellc = 0, mtu = ATM_NIF_MTU;
848 * Get IP interface and make sure its ready
850 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
851 if (inp->inf_nif == nip)
854 if ((inp == NULL) || (inp->inf_state != IPNIF_ACTIVE)) {
856 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
861 * Make sure we have services provider and ARP support
863 if ((inp->inf_serv == NULL) ||
864 (inp->inf_serv->is_arp_svcin == NULL)) {
866 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
871 * Check for LLC encapsulation
873 if ((ap->blli.tag_l2 == T_ATM_PRESENT) &&
874 (ap->blli.v.layer_2_protocol.ID_type == T_ATM_SIMPLE_ID) &&
875 (ap->blli.v.layer_2_protocol.ID.simple_ID == T_ATM_BLLI2_I8802)) {
877 mtu += IPATM_LLC_LEN;
881 * Verify requested MTU
883 if (ap->aal.type == ATM_AAL5) {
884 if ((ap->aal.v.aal5.forward_max_SDU_size > mtu) ||
885 (ap->aal.v.aal5.backward_max_SDU_size < mtu)) {
887 cause = T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED;
891 if ((ap->aal.v.aal4.forward_max_SDU_size > mtu) ||
892 (ap->aal.v.aal4.backward_max_SDU_size < mtu)) {
894 cause = T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED;
902 ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
905 cause = T_ATM_CAUSE_UNSPECIFIED_RESOURCE_UNAVAILABLE;
912 ivp->iv_flags = IVF_SVC;
915 ivp->iv_flags |= IVF_LLC;
918 * Lookup ARP entry for destination
920 switch ((*inp->inf_serv->is_arp_svcin)
921 (ivp, &ap->calling.addr, &ap->calling.subaddr)) {
925 * We'll be (hopefully) notified later
931 * We've got our answer already
933 ivp->iv_flags |= IVF_MAPOK;
934 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
939 * So sorry...come again
942 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
946 panic("ipatm_incoming: invalid arp_svcin return");
950 * Accept SVC connection
952 ivp->iv_state = IPVCC_PACCEPT;
955 * Save VCC information
959 /* ivp->iv_ = ap->headout; */
962 * Queue VCC onto its network interface
965 ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
968 * Wait for a CALL_CONNECTED event
970 IPVCC_TIMER(ivp, IPATM_SVC_TIME);
976 * Clean up after call failure
979 (*inp->inf_serv->is_arp_close)(ivp);
980 atm_free((caddr_t)ivp);
982 ap->cause.tag = T_ATM_PRESENT;
983 ap->cause.v = ipatm_cause;
984 ap->cause.v.cause_value = cause;
992 * This function will close an IP VCC (PVC or SVC), including notifying
993 * the signalling and ARP subsystems of the VCC's demise and cleaning
994 * up memory after ourselves.
1001 * 0 VCC successfully closed
1002 * errno close failed - reason indicated
1006 ipatm_closevc(struct ipvcc *ivp, int code)
1008 struct ip_nif *inp = ivp->iv_ipnif;
1012 * Make sure VCC hasn't been through here already
1014 switch (ivp->iv_state) {
1021 * Reset lookup cache
1023 if (last_map_ipvcc == ivp) {
1024 last_map_ipvcc = NULL;
1029 * Tell ARP about SVCs and dynamic PVCs
1031 if (inp->inf_serv &&
1032 ((ivp->iv_flags & IVF_SVC) || inp->inf_serv->is_arp_pvcopen)) {
1033 (*inp->inf_serv->is_arp_close)(ivp);
1037 * Free queued packets
1040 KB_FREEALL(ivp->iv_queue);
1050 switch (ivp->iv_state) {
1059 ipatm_cause.cause_value = code;
1060 err = atm_cm_release(ivp->iv_conn, &ipatm_cause);
1063 "ipatm_closevc: release fail: err=%d\n", err);
1072 "ipatm_closevc: unknown state: ivp=%p, state=%d\n",
1073 ivp, ivp->iv_state);
1077 * Remove VCC from network i/f
1080 DEQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
1083 * Reset state just to be sure
1085 ivp->iv_state = IPVCC_FREE;
1088 * If ARP module is done with VCC too, then free it
1090 if (ivp->iv_arpconn == NULL)
1091 atm_free((caddr_t)ivp);
1100 * Check if IP address is valid on a Network Interface
1102 * Checks whether the supplied IP address is allowed to be assigned to
1103 * the supplied IP network interface.
1107 * inp pointer to IP network interface
1111 * 1 - not valid to assign
1115 ipatm_chknif(struct in_addr in, struct ip_nif *inp)
1117 struct in_ifaddr *ia;
1121 * Make sure there's an interface requested
1127 * Make sure we have an IP address
1129 i = ntohl(in.s_addr);
1134 * Make sure an interface address is set
1141 * Make sure we're on the right subnet
1143 if ((i & ia->ia_subnetmask) != ia->ia_subnet)
1151 * Map an IP Address to an IP VCC
1153 * Given a destination IP address, this function will return a pointer
1154 * to the appropriate output IP VCC to which to send the packet.
1155 * This is currently implemented using a one-behind cache containing the
1156 * last successful mapping result. If the cache lookup fails, then a
1157 * simple linear search of all IP VCCs on the destination network interface
1158 * is performed. This is obviously an area to look at for performance
1162 * dst pointer to destination IP address
1163 * nip pointer to destination network interface
1166 * addr pointer to located IP VCC
1167 * 0 no such mapping exists
1171 ipatm_iptovc(struct sockaddr_in *dst, struct atm_nif *nip)
1175 u_long dstip = dst->sin_addr.s_addr;
1178 * Look in cache first
1180 if (last_map_ipdst == dstip)
1181 return (last_map_ipvcc);
1184 * Oh well, we've got to search for it...first find the interface
1187 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
1188 if (inp->inf_nif == nip)
1197 * Now home in on the VCC
1199 for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
1200 ivp = Q_NEXT(ivp, struct ipvcc, iv_elem)) {
1201 if (ivp->iv_dst.s_addr == dstip)
1206 * Update lookup cache
1209 last_map_ipdst = dstip;
1210 last_map_ipvcc = ivp;