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 $
34 * Virtual Channel Manager
38 #include <netatm/kern_include.h>
40 #include <netatm/ipatm/ipatm.h>
41 #include <netatm/ipatm/ipatm_var.h>
42 #include <netatm/ipatm/ipatm_serv.h>
45 __RCSID("@(#) $FreeBSD: src/sys/netatm/ipatm/ipatm_vcm.c,v 1.4 1999/08/28 00:48:45 peter Exp $");
49 Atm_attributes ipatm_aal5llc = {
125 T_ATM_NETWORK_CODING,
142 Atm_attributes ipatm_aal5null = {
144 CMAPI_CPCS, /* api */
146 sizeof(struct ifnet *), /* headin */
205 T_ATM_NETWORK_CODING,
222 Atm_attributes ipatm_aal4null = {
224 CMAPI_CPCS, /* api */
226 sizeof(struct ifnet *), /* headin */
285 T_ATM_NETWORK_CODING,
302 static struct t_atm_cause ipatm_cause = {
313 * This function will perform all actions necessary to activate a
314 * PVC for IP usage. In particular, it will allocate control blocks,
315 * open the PVC, initialize PVC stack, and initiate whatever ARP
316 * procedures are required.
319 * pvp pointer to PVC parameter structure
320 * sivp address to return pointer to IP PVC control block
323 * 0 PVC was successfully opened
324 * errno open failed - reason indicated
328 ipatm_openpvc(pvp, sivp)
329 struct ipatmpvc *pvp;
339 inp = pvp->ipp_ipnif;
343 * Make sure interface is ready to go
345 if (inp->inf_state != IPNIF_ACTIVE) {
351 * Validate fixed destination IP address
353 if (pvp->ipp_dst.sin_addr.s_addr != INADDR_ANY) {
354 #if (defined(BSD) && (BSD >= 199306))
355 if (in_broadcast(pvp->ipp_dst.sin_addr, &nip->nif_if) ||
357 if (in_broadcast(pvp->ipp_dst.sin_addr) ||
359 IN_MULTICAST(ntohl(pvp->ipp_dst.sin_addr.s_addr)) ||
360 ipatm_chknif(pvp->ipp_dst.sin_addr, inp)) {
367 * Allocate IP VCC block
369 ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
378 ivp->iv_flags = IVF_PVC;
379 if (pvp->ipp_encaps == ATM_ENC_LLC)
380 ivp->iv_flags |= IVF_LLC;
383 * Fill out connection attributes
385 if (pvp->ipp_aal == ATM_AAL5) {
386 if (pvp->ipp_encaps == ATM_ENC_LLC)
389 ap = &ipatm_aal5null;
391 ap = &ipatm_aal4null;
395 ap->traffic.v.forward.PCR_all_traffic = nip->nif_pif->pif_pcr;
396 ap->traffic.v.backward.PCR_all_traffic = nip->nif_pif->pif_pcr;
397 ap->called.addr.address_format = T_ATM_PVC_ADDR;
398 ap->called.addr.address_length = sizeof(Atm_addr_pvc);
399 pvcp = (Atm_addr_pvc *)ap->called.addr.address;
400 ATM_PVC_SET_VPI(pvcp, pvp->ipp_vpi);
401 ATM_PVC_SET_VCI(pvcp, pvp->ipp_vci);
402 ap->called.subaddr.address_format = T_ATM_ABSENT;
403 ap->called.subaddr.address_length = 0;
408 err = atm_cm_connect(&ipatm_endpt, ivp, ap, &ivp->iv_conn);
410 atm_free((caddr_t)ivp);
415 * Save PVC information and link in VCC
417 /* ivp->iv_ = ap->headout; */
420 * Queue VCC onto its network interface
424 ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
429 * Set destination IP address and IPVCC state
431 if (pvp->ipp_dst.sin_addr.s_addr == INADDR_ANY) {
433 * Initiate ARP processing
435 switch ((*inp->inf_serv->is_arp_pvcopen)(ivp)) {
441 ivp->iv_state = IPVCC_ACTIVE;
446 * We've got our answer already
448 ivp->iv_state = IPVCC_ACTIVE;
449 ivp->iv_flags |= IVF_MAPOK;
450 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
457 ivp->iv_state = IPVCC_ACTPENT;
458 IPVCC_TIMER(ivp, 1 * ATM_HZ);
462 panic("ipatm_openpvc: invalid arp_pvcopen return");
467 * Use configured IP destination
469 ivp->iv_dst.s_addr = pvp->ipp_dst.sin_addr.s_addr;
470 ivp->iv_state = IPVCC_ACTIVE;
471 ivp->iv_flags |= IVF_MAPOK;
486 * This function will initiate the creation of an IP SVC. The IP VCC
487 * control block will be initialized and, if required, we will initiate
488 * ARP processing in order to resolve the destination's ATM address. Once
489 * the destination ATM address is known, ipatm_opensvc() will be called.
492 * ifp pointer to destination ifnet structure
493 * daf destination address family type
494 * dst pointer to destination address
495 * sivp address to return pointer to IP SVC control block
498 * 0 SVC creation was successfully initiated
499 * errno creation failed - reason indicated
503 ipatm_createsvc(ifp, daf, dst, sivp)
509 struct atm_nif *nip = (struct atm_nif *)ifp;
517 * Get IP interface and make sure its ready
519 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
520 if (inp->inf_nif == nip)
527 if (inp->inf_state != IPNIF_ACTIVE) {
533 * Validate destination address
535 if (daf == AF_INET) {
537 * Destination is IP address
539 ip = (struct in_addr *)dst;
541 if (ip->s_addr == INADDR_ANY) {
545 } else if (daf == AF_ATM) {
547 * Destination is ATM address
549 atm = (Atm_addr *)dst;
551 if (atm->address_format == T_ATM_ABSENT) {
561 * Make sure we have services provider and ARP support
563 if ((inp->inf_serv == NULL) ||
564 (inp->inf_serv->is_arp_svcout == NULL)) {
572 ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
581 ivp->iv_flags = IVF_SVC;
585 * Get destination ATM address
587 if (daf == AF_INET) {
591 ivp->iv_dst.s_addr = ip->s_addr;
593 switch ((*inp->inf_serv->is_arp_svcout)(ivp, ip)) {
599 ivp->iv_state = IPVCC_PMAP;
600 IPVCC_TIMER(ivp, IPATM_ARP_TIME);
605 * We've got our answer already, so open SVC
607 ivp->iv_flags |= IVF_MAPOK;
608 err = ipatm_opensvc(ivp);
610 (*inp->inf_serv->is_arp_close)(ivp);
611 atm_free((caddr_t)ivp);
618 * So sorry...come again
620 atm_free((caddr_t)ivp);
625 panic("ipatm_createsvc: invalid arp_svcout return");
629 * We were given the ATM address, so open the SVC
631 * Create temporary arp map entry so that opensvc() works.
632 * Caller must set up a permanent entry immediately! (yuk)
636 ATM_ADDR_COPY(atm, &map.am_dstatm);
637 map.am_dstatmsub.address_format = T_ATM_ABSENT;
638 map.am_dstatmsub.address_length = 0;
639 ivp->iv_arpent = ↦
640 err = ipatm_opensvc(ivp);
642 atm_free((caddr_t)ivp);
645 ivp->iv_arpent = NULL;
649 * Queue VCC onto its network interface
653 ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
668 * This function will continue the IP SVC creation process. Here, we
669 * will issue an SVC open to the signalling manager and then wait for
670 * the final SVC setup results.
673 * ivp pointer to IP SVC to open
676 * 0 SVC open was successfully initiated
677 * errno open failed - reason indicated
684 struct ip_nif *inp = ivp->iv_ipnif;
689 * Cancel possible arp timeout
694 * Fill out connection attributes
697 if (inp->inf_serv->is_vccparm[i].ivc_aal == ATM_AAL5) {
698 if (inp->inf_serv->is_vccparm[i].ivc_encaps == ATM_ENC_LLC) {
700 ivp->iv_flags |= IVF_LLC;
702 ap = &ipatm_aal5null;
703 ivp->iv_flags &= ~IVF_LLC;
706 ap = &ipatm_aal4null;
707 ivp->iv_flags &= ~IVF_LLC;
710 ap->nif = inp->inf_nif;
711 ap->traffic.v.forward.PCR_all_traffic = inp->inf_nif->nif_pif->pif_pcr;
712 ap->traffic.v.backward.PCR_all_traffic = inp->inf_nif->nif_pif->pif_pcr;
714 ATM_ADDR_COPY(&ivp->iv_arpent->am_dstatm, &ap->called.addr);
715 ATM_ADDR_COPY(&ivp->iv_arpent->am_dstatmsub, &ap->called.subaddr);
720 err = atm_cm_connect(&ipatm_endpt, ivp, ap, &ivp->iv_conn);
725 * Call is progressing
727 /* ivp->iv_ = ap->headout; */
730 * Now we just wait for a CALL_CONNECTED event
732 ivp->iv_state = IPVCC_POPEN;
733 IPVCC_TIMER(ivp, IPATM_SVC_TIME);
739 * We've been hooked up with a shared VCC
741 /* ivp->iv_ = ap->headout; */
751 * Retry an IP SVC Open
753 * This function will attempt to retry a failed SVC open request. The IP
754 * interface service provider specifies a list of possible VCC parameters
755 * for IP to use. We will try each set of parameters in turn until either
756 * an open succeeds or we reach the end of the list.
759 * ivp pointer to IP SVC
762 * 0 SVC (re)open was successfully initiated
770 struct ip_nif *inp = ivp->iv_ipnif;
773 * If there isn't another set of vcc parameters to try, return
775 if ((++ivp->iv_parmx >= IPATM_VCCPARMS) ||
776 (inp->inf_serv->is_vccparm[ivp->iv_parmx].ivc_aal == 0))
780 * Okay, now initiate open with a new set of parameters
782 return (ipatm_opensvc(ivp));
787 * Finish IP SVC Activation
790 * ivp pointer to IP SVC
802 * Connection is now active
804 ivp->iv_state = IPVCC_ACTIVE;
808 * Tell ARP module that connection is active
810 if ((*ivp->iv_ipnif->inf_serv->is_arp_svcact)(ivp)) {
811 (void) ipatm_closevc(ivp, T_ATM_CAUSE_TEMPORARY_FAILURE);
816 * Send any queued packet
818 if ((ivp->iv_flags & IVF_MAPOK) && ivp->iv_queue) {
819 struct sockaddr_in sin;
822 sin.sin_family = AF_INET;
823 sin.sin_addr.s_addr = ivp->iv_dst.s_addr;
824 ifp = (struct ifnet *)ivp->iv_ipnif->inf_nif;
825 (void) ipatm_ifoutput(ifp, ivp->iv_queue,
826 (struct sockaddr *)&sin);
827 ivp->iv_queue = NULL;
833 * Process Incoming Calls
835 * This function will receive control when an incoming call has been matched
836 * to one of our registered listen parameter blocks. Assuming the call passes
837 * acceptance criteria and all required resources are available, we will
838 * create an IP SVC and notify the connection manager of our decision. We
839 * will then await notification of the final SVC setup results. If any
840 * problems are encountered, we will just tell the connection manager to
846 * tok owner's matched listening token
847 * cop pointer to incoming call's connection block
848 * ap pointer to incoming call's attributes
849 * tokp pointer to location to store our connection token
853 * errno call rejected - reason indicated
857 ipatm_incoming(tok, cop, ap, tokp)
863 struct atm_nif *nip = ap->nif;
865 struct ipvcc *ivp = NULL;
867 int usellc = 0, mtu = ATM_NIF_MTU;
870 * Get IP interface and make sure its ready
872 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
873 if (inp->inf_nif == nip)
876 if ((inp == NULL) || (inp->inf_state != IPNIF_ACTIVE)) {
878 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
883 * Make sure we have services provider and ARP support
885 if ((inp->inf_serv == NULL) ||
886 (inp->inf_serv->is_arp_svcin == NULL)) {
888 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
893 * Check for LLC encapsulation
895 if ((ap->blli.tag_l2 == T_ATM_PRESENT) &&
896 (ap->blli.v.layer_2_protocol.ID_type == T_ATM_SIMPLE_ID) &&
897 (ap->blli.v.layer_2_protocol.ID.simple_ID == T_ATM_BLLI2_I8802)) {
899 mtu += IPATM_LLC_LEN;
903 * Verify requested MTU
905 if (ap->aal.type == ATM_AAL5) {
906 if ((ap->aal.v.aal5.forward_max_SDU_size > mtu) ||
907 (ap->aal.v.aal5.backward_max_SDU_size < mtu)) {
909 cause = T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED;
913 if ((ap->aal.v.aal4.forward_max_SDU_size > mtu) ||
914 (ap->aal.v.aal4.backward_max_SDU_size < mtu)) {
916 cause = T_ATM_CAUSE_AAL_PARAMETERS_NOT_SUPPORTED;
924 ivp = (struct ipvcc *)atm_allocate(&ipatm_vcpool);
927 cause = T_ATM_CAUSE_UNSPECIFIED_RESOURCE_UNAVAILABLE;
934 ivp->iv_flags = IVF_SVC;
937 ivp->iv_flags |= IVF_LLC;
940 * Lookup ARP entry for destination
942 switch ((*inp->inf_serv->is_arp_svcin)
943 (ivp, &ap->calling.addr, &ap->calling.subaddr)) {
947 * We'll be (hopefully) notified later
953 * We've got our answer already
955 ivp->iv_flags |= IVF_MAPOK;
956 ivp->iv_dst.s_addr = ivp->iv_arpent->am_dstip.s_addr;
961 * So sorry...come again
964 cause = T_ATM_CAUSE_SERVICE_OR_OPTION_UNAVAILABLE;
968 panic("ipatm_incoming: invalid arp_svcin return");
972 * Accept SVC connection
974 ivp->iv_state = IPVCC_PACCEPT;
977 * Save VCC information
981 /* ivp->iv_ = ap->headout; */
984 * Queue VCC onto its network interface
987 ENQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
990 * Wait for a CALL_CONNECTED event
992 IPVCC_TIMER(ivp, IPATM_SVC_TIME);
998 * Clean up after call failure
1001 (*inp->inf_serv->is_arp_close)(ivp);
1002 atm_free((caddr_t)ivp);
1004 ap->cause.tag = T_ATM_PRESENT;
1005 ap->cause.v = ipatm_cause;
1006 ap->cause.v.cause_value = cause;
1014 * This function will close an IP VCC (PVC or SVC), including notifying
1015 * the signalling and ARP subsystems of the VCC's demise and cleaning
1016 * up memory after ourselves.
1019 * ivp pointer to VCC
1023 * 0 VCC successfully closed
1024 * errno close failed - reason indicated
1028 ipatm_closevc(ivp, code)
1032 struct ip_nif *inp = ivp->iv_ipnif;
1036 * Make sure VCC hasn't been through here already
1038 switch (ivp->iv_state) {
1045 * Reset lookup cache
1047 if (last_map_ipvcc == ivp) {
1048 last_map_ipvcc = NULL;
1053 * Tell ARP about SVCs and dynamic PVCs
1055 if (inp->inf_serv &&
1056 ((ivp->iv_flags & IVF_SVC) || inp->inf_serv->is_arp_pvcopen)) {
1057 (*inp->inf_serv->is_arp_close)(ivp);
1061 * Free queued packets
1064 KB_FREEALL(ivp->iv_queue);
1074 switch (ivp->iv_state) {
1083 ipatm_cause.cause_value = code;
1084 err = atm_cm_release(ivp->iv_conn, &ipatm_cause);
1087 "ipatm_closevc: release fail: err=%d\n", err);
1096 "ipatm_closevc: unknown state: ivp=%p, state=%d\n",
1097 ivp, ivp->iv_state);
1101 * Remove VCC from network i/f
1104 DEQUEUE(ivp, struct ipvcc, iv_elem, inp->inf_vcq);
1107 * Reset state just to be sure
1109 ivp->iv_state = IPVCC_FREE;
1112 * If ARP module is done with VCC too, then free it
1114 if (ivp->iv_arpconn == NULL)
1115 atm_free((caddr_t)ivp);
1124 * Check if IP address is valid on a Network Interface
1126 * Checks whether the supplied IP address is allowed to be assigned to
1127 * the supplied IP network interface.
1131 * inp pointer to IP network interface
1135 * 1 - not valid to assign
1139 ipatm_chknif(in, inp)
1143 struct in_ifaddr *ia;
1147 * Make sure there's an interface requested
1153 * Make sure we have an IP address
1155 i = ntohl(in.s_addr);
1160 * Make sure an interface address is set
1167 * Make sure we're on the right subnet
1169 if ((i & ia->ia_subnetmask) != ia->ia_subnet)
1177 * Map an IP Address to an IP VCC
1179 * Given a destination IP address, this function will return a pointer
1180 * to the appropriate output IP VCC to which to send the packet.
1181 * This is currently implemented using a one-behind cache containing the
1182 * last successful mapping result. If the cache lookup fails, then a
1183 * simple linear search of all IP VCCs on the destination network interface
1184 * is performed. This is obviously an area to look at for performance
1188 * dst pointer to destination IP address
1189 * nip pointer to destination network interface
1192 * addr pointer to located IP VCC
1193 * 0 no such mapping exists
1197 ipatm_iptovc(dst, nip)
1198 struct sockaddr_in *dst;
1199 struct atm_nif *nip;
1203 u_long dstip = dst->sin_addr.s_addr;
1207 * Look in cache first
1209 if (last_map_ipdst == dstip)
1210 return (last_map_ipvcc);
1213 * Oh well, we've got to search for it...first find the interface
1216 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
1217 if (inp->inf_nif == nip)
1226 * Now home in on the VCC
1228 for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
1229 ivp = Q_NEXT(ivp, struct ipvcc, iv_elem)) {
1230 if (ivp->iv_dst.s_addr == dstip)
1235 * Update lookup cache
1238 last_map_ipdst = dstip;
1239 last_map_ipvcc = ivp;