From: chas w. <ch...@us...> - 2005-02-13 17:47:38
|
Update of /cvsroot/linux-atm/linux-atm/src/sigd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24189/src/sigd Modified Files: Tag: V2_5_0 kernel.c proto.c proto.h sap.c timeout.c timeout.h uni.c Log Message: point 2 multipoint signalling Index: kernel.c =================================================================== RCS file: /cvsroot/linux-atm/linux-atm/src/sigd/kernel.c,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -d -r1.2 -r1.2.2.1 *** kernel.c 9 Oct 2001 22:33:07 -0000 1.2 --- kernel.c 13 Feb 2005 17:47:22 -0000 1.2.2.1 *************** *** 31,34 **** --- 31,139 ---- + #ifdef MULTIPOINT + int send_dropparty(SOCKET *sock) + { + Q_DSC dsc; + int size; + + q_create(&dsc, q_buffer, MAX_Q_MSG); + q_assign(&dsc, QF_msg_type, ATM_MSG_DROP_PARTY); + q_assign(&dsc, QF_call_ref, sock->call_ref); + q_assign(&dsc, QF_ep_ref, sock->ep_ref); + q_assign(&dsc, QF_cause, ATM_CV_NORMAL_UNSPEC); + if ((size = q_close(&dsc)) < 0) + return -EINVAL; + + to_signaling(sock->sig, q_buffer, size); + START_TIMER(sock, T398); + return 0; + } + + + int send_addparty(SOCKET *sock, struct sockaddr_atmsvc *svc) + { + SOCKET *walk = NULL; + Q_DSC dsc; + struct sockaddr_atmsvc *local = NULL; + int error = 0,size,max_ep_ref = 0; + char buf[80]; + + diag(COMPONENT, DIAG_INFO, "send_addparty"); + q_create(&dsc,q_buffer,MAX_Q_MSG); + + /* think this next line is already done */ + /* sock->sig = route_remote(&sock->remote); */ + + /* set the calling party address */ + if (sock->sig && sock->sig->mode == sm_switch) local = &sock->local; + if (atmsvc_addr_in_use(sock->local) && !local) { + sock->sig = route_local(&sock->local); + if (sock->sig) local = &sock->local; + else { + error = -EADDRNOTAVAIL; + diag(COMPONENT,DIAG_WARN,"local address no longer available"); + } + } + else { + if (!sock->sig) error = -EHOSTUNREACH; + else { + if (!local) local = get_local(sock->sig); + if (!local) local = get_local(NULL); + if (local) sock->local = *local; + else { + error = -EADDRNOTAVAIL; + diag(COMPONENT,DIAG_ERROR,"no local address"); + } + } + } + if (local) { + if (*local->sas_addr.pub) { + q_assign(&dsc,QF_cgpn_plan,ATM_NP_E164); + q_assign(&dsc,QF_cgpn_type,ATM_TON_INTRNTNL); + q_write(&dsc,QF_cgpn,(void *) local->sas_addr.pub, + strlen(local->sas_addr.pub)); + } + else { + q_assign(&dsc,QF_cgpn_plan,ATM_NP_AEA); + q_assign(&dsc,QF_cgpn_type,ATM_TON_UNKNOWN); + q_write(&dsc,QF_cgpn,(void *) local->sas_addr.prv,ATM_ESA_LEN); + } + } + + /* what to do if error == -EADDRNOTAVAIL ? */ + + /* find the largest endpoint reference in the list */ + for (walk = sockets; walk->next; walk = walk->next) { + if ((walk->call_ref == sock->call_ref) && + (walk->ep_ref > max_ep_ref)) max_ep_ref = walk->ep_ref; + } + sock->ep_ref = max_ep_ref + 1; + + q_assign(&dsc,QF_call_ref,sock->call_ref); + q_assign(&dsc,QF_aal_type,5); /* AAL 5 */ + q_assign(&dsc,QF_msg_type,ATM_MSG_ADD_PARTY); + + diag(COMPONENT, DIAG_INFO, "send_addparty: sap_encode"); + if (atm2text(buf,MAX_ATM_ADDR_LEN+1,(struct sockaddr *)svc, pretty) >= 0) + diag(COMPONENT, DIAG_INFO, "send_addparty -> %s", buf); + else + diag(COMPONENT, DIAG_INFO, "send_addparty: invalid nsap address"); + error = sap_encode(&dsc,svc,&sock->sap,NULL,sock->sig->uni,sock->sig->max_rate); + diag(COMPONENT, DIAG_INFO, "send_addparty: sap_encode error = %d", error); + + q_assign(&dsc, QF_ep_ref, sock->ep_ref); + error = 0; + if ((size = q_close(&dsc)) < 0) { + error = -EINVAL; + } else if (!error) { + to_signaling(sock->sig,q_buffer,size); + new_state(sock,ss_connecting); + return sock->ep_ref; + } + return error; + } + #endif + + static int send_setup(SOCKET *sock) { *************** *** 97,101 **** --- 202,218 ---- sock->sig->uni,sock->sig->max_rate); q_assign(&dsc,QF_bearer_class,16); /* BCOB-X */ + #ifndef MULTIPOINT q_assign(&dsc,QF_upcc,0); /* p2p */ + #else + if (sock->ct == p2p) { + diag(COMPONENT, DIAG_INFO, "setting configuration to point-to-point"); + q_assign(&dsc,QF_upcc,0); /* p2p */ + } else if (sock->ct == p2mp) { + diag(COMPONENT, DIAG_INFO, "setting configuration to multipoint"); + q_assign(&dsc, QF_upcc, 1); /* p2mp */ + q_assign(&dsc, QF_ep_ref, 0); /* initial setup always leaf 0 */ + sock->ep_ref = 0; + } + #endif #if !defined(UNI30) || defined(DYNAMIC_UNI) if (!error && sock->sig->uni != S_UNI30) *************** *** 231,234 **** --- 348,356 ---- sock->state = ss_connecting; sock->pvc = msg->pvc; + #ifdef MULTIPOINT + sock->ct = p2p; + if (msg->session > 0) + sock->ct = p2mp; + #endif error = send_setup(sock); if (error) { *************** *** 314,318 **** send_close(sock); /* fall through */ ! case ss_wait_close: free_sock(sock); /* fall through */ --- 436,440 ---- send_close(sock); /* fall through */ ! case ss_wait_close: /* network requested close */ free_sock(sock); /* fall through */ *************** *** 359,362 **** --- 481,485 ---- case ss_rel_ind: send_release_complete(sock->sig,sock->call_ref,0); /* @@@ */ + diag(COMPONENT, DIAG_INFO, "ss_rel_ind"); free_sock(sock); return; *************** *** 479,482 **** --- 602,685 ---- } #endif + #ifdef MULTIPOINT + case as_dropparty: { + int leaves; + + /* This should send a RELEASE if there is only + * one party left on the call + */ + + if (sock == NULL) { + /* leaf was probably not found */ + send_kernel(msg->vcc, kptr_null, as_dropparty, -1, + NULL, NULL, NULL, NULL, NULL); + return; + } + leaves = count_leaves(&sock->id); + if ((sock->state == ss_connected) || + (sock->state == ss_connecting)) { + /* rely on short circuit boolean eval */ + if ((leaves > 1) && (send_dropparty(sock) < 0)) { + send_kernel(sock->id, kptr_null, as_error, 0, + NULL, NULL, NULL, NULL, NULL); + } else if (leaves > 1) { + new_state(sock, ss_rel_req); + } else if (leaves == 1) { + send_release(sock, sock->sig->uni + != S_UNI30 ? ATM_CV_NORMAL_CLEAR : + ATM_CV_NORMAL_UNSPEC); + } + } else { + send_kernel(sock->id, kptr_null, as_error, 0, + NULL, NULL, NULL, NULL, NULL); + } + return; + } + + case as_addparty: + { + int leafid = -1; + SOCKET *ns = NULL; + + if (sock == NULL) { + diag(COMPONENT, DIAG_INFO, + "*sock is null. Not adding party."); + } else { + /* Create a new socket for keeping state information + * that has the same "id" and call reference value + * as *sock, but should have a different endpoint + * reference. Need to make sure that all routines + * that search for SOCKETS by id also compare endpoint + * references */ + + ns = new_sock(msg->vcc); + ns->call_ref = sock->call_ref; + + ns->local = msg->local; + ns->remote = msg->svc; + ns->qos = msg->qos; + ns->sap = msg->sap; + ns->state = ss_connecting; + ns->pvc = msg->pvc; + ns->sig = route_remote(&ns->remote); + leafid = send_addparty(ns, &msg->svc); + START_TIMER(ns,T399); + } + + if (leafid > 0) { + /* don't do anything here because we will notify + * the kernel of success or failure after the + * network responds with ATM_MSG_ADD_PARTY_ACK or + * ATM_MSG_ADD_PARTY_REJ */ + } else { + /* notify kernel of failure because the addparty + * request was never sent */ + diag(COMPONENT, DIAG_INFO, "send_addparty failed"); + send_kernel(ns->id, kptr_null, as_error, 0, + NULL, NULL, NULL, NULL, NULL); + } + return; + } + #endif default: diag(COMPONENT,DIAG_WARN,"invalid message %d",(int) msg->type); *************** *** 578,581 **** --- 781,795 ---- break; } + #ifdef MULTIPOINT + else if (msg->type == as_dropparty) { + /* check the endpoint reference while we search */ + dispatcher = dispatch; + for (curr = sockets; curr; curr = curr->next) { + if (kptr_eq(&msg->vcc, &curr->id) && + (curr->ep_ref == msg->reply)) break; + } + if (curr == NULL) diag(COMPONENT, DIAG_INFO, "leaf not found"); + } + #endif else { dispatcher = dispatch; Index: proto.c =================================================================== RCS file: /cvsroot/linux-atm/linux-atm/src/sigd/proto.c,v retrieving revision 1.2.2.2 retrieving revision 1.2.2.3 diff -C2 -d -r1.2.2.2 -r1.2.2.3 *** proto.c 10 Dec 2004 17:54:50 -0000 1.2.2.2 --- proto.c 13 Feb 2005 17:47:22 -0000 1.2.2.3 *************** *** 43,47 **** const char *as_name[] = { "<invalid>","as_bind","as_connect","as_accept", "as_reject","as_listen","as_okay","as_error","as_indicate","as_close", ! "as_itf_notify","as_modify","as_identify","as_terminate" }; const CALL_STATE state_map[] = { /* formatting aligned with STATE */ --- 43,51 ---- const char *as_name[] = { "<invalid>","as_bind","as_connect","as_accept", "as_reject","as_listen","as_okay","as_error","as_indicate","as_close", ! "as_itf_notify","as_modify","as_identify","as_terminate", ! #ifdef MULTPOINT ! "as_addparty", "as_dropparty", ! #endif ! }; const CALL_STATE state_map[] = { /* formatting aligned with STATE */ *************** *** 121,124 **** --- 125,157 ---- } + #ifdef MULTIPOINT + /* don't call free_sock() after free_leaves() -- this function frees the + * root node as well */ + void free_leaves(atm_kptr_t *id) + { + SOCKET **walk = &sockets, *target = NULL; + while (*walk != NULL) { + target = *walk; + walk = &((*walk)->next); + if (kptr_eq(&target->id, id)) { + diag(COMPONENT, DIAG_INFO, "freeing leaf %s:%d", + kptr_print(&target->id), target->ep_ref); + free_sock(target); + } + } + } + + int count_leaves(atm_kptr_t *id) + { + SOCKET *walk = sockets; + + int count = 0; + if (walk) + for (; walk; walk = walk->next) + if(kptr_eq(&walk->id, id)) + count++; + return count; + } + #endif void new_state(SOCKET *sock,STATE state) Index: proto.h =================================================================== RCS file: /cvsroot/linux-atm/linux-atm/src/sigd/proto.h,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -d -r1.2 -r1.2.2.1 *** proto.h 9 Oct 2001 22:33:07 -0000 1.2 --- proto.h 13 Feb 2005 17:47:22 -0000 1.2.2.1 *************** *** 14,17 **** --- 14,20 ---- #include "saal.h" + #ifdef MULTIPOINT + typedef enum { p2p, p2mp } CALL_TYPE; + #endif typedef enum { /* formatting aligned with state_map and others */ *************** *** 79,82 **** --- 82,88 ---- struct sockaddr_atmsvc local; /* local address */ struct sockaddr_atmsvc remote; /* remote address */ + #ifdef MULTIPOINT + CALL_TYPE ct; + #endif struct atm_sap sap; /* SAP (BHLI and BLLI) */ struct atm_qos qos; /* QOS parameters */ *************** *** 153,156 **** --- 159,164 ---- SOCKET *new_sock(atm_kptr_t id); void free_sock(SOCKET *sock); + void free_leaves(atm_kptr_t *id); + int count_leaves(atm_kptr_t *id); void new_state(SOCKET *sock,STATE state); SOCKET *lookup_sap(const struct sockaddr_atmsvc *addr, Index: sap.c =================================================================== RCS file: /cvsroot/linux-atm/linux-atm/src/sigd/sap.c,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -d -r1.2 -r1.2.2.1 *** sap.c 9 Oct 2001 22:33:07 -0000 1.2 --- sap.c 13 Feb 2005 17:47:22 -0000 1.2.2.1 *************** *** 143,146 **** --- 143,147 ---- q_write(dsc,QF_cdpn_esa,(void *) addr->sas_addr.prv,ATM_ESA_LEN); else return -EDESTADDRREQ; + if (qos) { if (qos->txtp.traffic_class == ATM_UBR || qos->rxtp.traffic_class == ATM_UBR) { *************** *** 196,199 **** --- 197,201 ---- q_assign(dsc,QF_bw_max_sdu,qos->rxtp.max_sdu); } + } /* @@@ bearer class ? */ /* @@@ QOS class ? */ Index: timeout.c =================================================================== RCS file: /cvsroot/linux-atm/linux-atm/src/sigd/timeout.c,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -d -r1.2 -r1.2.2.1 *** timeout.c 9 Oct 2001 22:33:07 -0000 1.2 --- timeout.c 13 Feb 2005 17:47:22 -0000 1.2.2.1 *************** *** 30,33 **** --- 30,57 ---- } + #ifdef MULTIPOINT + void on_T398(void *user) /* DROPPARTY */ + { + SOCKET *sock = user; + + if (sock == NULL) return; + SEND_ERROR(sock->id, -ETIMEDOUT); + /* should retry once and then give up */ + sock->conn_timer = NULL; + free_sock(sock); + } + + void on_T399(void *user) /* ADDPARTY */ + { + SOCKET *sock = user; + + if (sock == NULL) return; + diag(COMPONENT,DIAG_INFO,"Timer T399 expired in state %s", + state_name[sock->state]); + SEND_ERROR(sock->id, -ETIMEDOUT); + sock->conn_timer = NULL; + free_sock(sock); + } + #endif void on_T303(void *user) /* CONNECTING */ Index: timeout.h =================================================================== RCS file: /cvsroot/linux-atm/linux-atm/src/sigd/timeout.h,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -d -r1.2 -r1.2.2.1 *** timeout.h 9 Oct 2001 22:33:07 -0000 1.2 --- timeout.h 13 Feb 2005 17:47:22 -0000 1.2.2.1 *************** *** 16,20 **** #define T360_TIME 30000000 /* 30 sec */ #define T361_TIME 20000000 /* 20 sec */ ! #define START_TIMER(u,t) { assert(!u->conn_timer); \ --- 16,21 ---- #define T360_TIME 30000000 /* 30 sec */ #define T361_TIME 20000000 /* 20 sec */ ! #define T399_TIME 14000000 /* 14 sec */ ! #define T398_TIME 4000000 /* 4 sec */ #define START_TIMER(u,t) { assert(!u->conn_timer); \ *************** *** 23,26 **** --- 24,29 ---- + void on_T398(void *user); + void on_T399(void *user); void on_T303(void *user); void on_T308_1(void *user); Index: uni.c =================================================================== RCS file: /cvsroot/linux-atm/linux-atm/src/sigd/uni.c,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -C2 -d -r1.2 -r1.2.2.1 *** uni.c 9 Oct 2001 22:33:07 -0000 1.2 --- uni.c 13 Feb 2005 17:47:22 -0000 1.2.2.1 *************** *** 517,521 **** case ss_wait_rel: STOP_TIMER(sock); ! free_sock(sock); return; #if defined(Q2963_1) || defined(DYNAMIC_UNI) --- 517,527 ---- case ss_wait_rel: STOP_TIMER(sock); ! #ifdef MULTIPOINT ! /* Need to free all endpoints if this is a pmp call */ ! if (sock->ct == p2mp) ! free_leaves(&sock->id); ! else ! #endif ! free_sock(sock); return; #if defined(Q2963_1) || defined(DYNAMIC_UNI) *************** *** 574,577 **** --- 580,623 ---- /* silently ignore this junk */ return; + #ifdef MULTIPOINT + case ATM_MSG_ADD_PARTY_REJ: + STOP_TIMER(sock); + send_drop_party_ack(sock->sig,sock->call_ref,sock->ep_ref,ATM_CV_CALL_REJ); + send_kernel(sock->id, kptr_null, as_addparty, -1, + NULL, NULL, NULL, NULL, NULL); + diag(COMPONENT, DIAG_INFO, "addparty failed"); + /* If no other leaves, should close entire call */ + free_sock(sock); + return; + case ATM_MSG_ADD_PARTY_ACK: + STOP_TIMER(sock); + send_kernel(sock->id, kptr_null, as_addparty, sock->ep_ref, + NULL, NULL, NULL, NULL, NULL); + diag(COMPONENT, DIAG_INFO, "addparty succeeded"); + new_state(sock, ss_connected); + return; + case ATM_MSG_DROP_PARTY_ACK: + STOP_TIMER(sock); + send_kernel(sock->id, kptr_null, as_dropparty, 0, + NULL, NULL, NULL, NULL, NULL); + diag(COMPONENT, DIAG_INFO, "dropparty succeeded"); + free_sock(sock); + return; + case ATM_MSG_DROP_PARTY: + diag(COMPONENT, DIAG_INFO, "received dropparty"); + switch (sock->state) { + case ss_connecting: + case ss_connected: + case ss_rel_req: + case ss_wait_rel: + send_drop_party_ack(sock->sig, sock->call_ref, sock->ep_ref, + ATM_CV_NORMAL_CLEAR); + break; + default: + send_drop_party_ack(sock->sig, sock->call_ref, sock->ep_ref, 0); + } + free_sock(sock); + return; + #endif #if defined(Q2963_1) || defined(DYNAMIC_UNI) /* *************** *** 706,709 **** --- 752,756 ---- SOCKET *curr; unsigned long call_ref; + unsigned short ep_ref; unsigned char mid; *************** *** 752,757 **** return; } ! for (curr = sockets; curr; curr = curr->next) ! if (curr->sig == sig && curr->call_ref == call_ref) break; diag(COMPONENT,DIAG_DEBUG,"FROM SAAL %d.%d.%d: %s (0x%02X) CR 0x%06lx for " "%s",S_PVC(sig),mid2name(((unsigned char *) msg)[5]), --- 799,814 ---- return; } ! ! #ifdef MULTIPOINT ! if (q_present(&in_dsc,QF_ep_ref)) { ! ep_ref = cvt_ep_ref(sig,q_fetch(&in_dsc,QF_ep_ref)); ! for (curr = sockets; curr; curr = curr->next) ! if (curr->sig == sig && ! curr->call_ref == call_ref && ! curr->ep_ref == ep_ref) break; ! } else ! #endif ! for (curr = sockets; curr; curr = curr->next) ! if (curr->sig == sig && curr->call_ref == call_ref) break; diag(COMPONENT,DIAG_DEBUG,"FROM SAAL %d.%d.%d: %s (0x%02X) CR 0x%06lx for " "%s",S_PVC(sig),mid2name(((unsigned char *) msg)[5]), *************** *** 767,772 **** if (curr && q_present(&in_dsc,QF_ep_ref) && mid != ATM_MSG_ADD_PARTY && mid != ATM_MSG_DROP_PARTY_ACK) { - unsigned short ep_ref; - ep_ref = cvt_ep_ref(sig,q_fetch(&in_dsc,QF_ep_ref)); if (curr->ep_ref != ep_ref) { --- 824,827 ---- |