[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]
Communications Programming Concepts

Sending Data on an ATM Socket Rate-Enforced SVC Client Example Program

This program must be compiled with the -D_BSD and -lbsd options. For example, use the cc prog.c -o prog -D_BSD -lbsd command.

/*
 * ATM Sockets rate enforced SVC Client Example
 *
 * This program opens a opens a rate enforced (not best effort) SVC
 * and sends data on it.
 *
 */
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/ndd_var.h>
#include <sys/atmsock.h>
#define BUFF_SIZE       100000
char    buff[BUFF_SIZE];
main(argc, argv)
        int argc;
        char *argv[];
{
   int                     s;          // Socket file descriptor
   int                     error;      // Function return code
   int                     i;
   sockaddr_ndd_atm_t      addr;       // ATM Socket Address
   unsigned long           size;       // Size of socket argument
   aal_parm_t              aal_parm;   // AAL parameters
   blli_t                  blli[3];    // Broadband Lower Layer Info
   traffic_des_t           traffic;    // Traffic Descriptor
   bearer_t                bearer;     // Broadband Bearer Capability
   int                     o[20];      // Temporary variable for ATM
                                       // address
   cause_t                 cause;      // Cause of failure
   unsigned char           max_pend;   // Maximum outstanding transmits
   // Create a socket in the AF_NDD domain of type SOCK_CONN_DGRAM
   // and NDD_PROT_ATM protocol.
   s = socket(AF_NDD, SOCK_CONN_DGRAM, NDD_PROT_ATM);
   if (s == -1) {
      perror("socket");
      exit(-1);
   }
   addr.sndd_atm_len = sizeof(addr);
   addr.sndd_atm_family = AF_NDD;
   strcpy( addr.sndd_atm_nddname, "atm0" );
   // The bind command associates this socket with a particular
   // ATM device, as specified by addr.sndd_atm_nddname.
   error = bind( s, (struct sockaddr *)&addr, sizeof(addr) );
   if (error) {         // An error from bind would indicate the
      perror("bind");   // requested ATM device is not available.
      exit(-1);         // Check smitty devices.
   } /* endif */
   // Set the AAL parameters.
   // See the ATM UNI 3.0 for valid combinations.
   // For a rate enforced connection the adapter will segment
   // according to the fwd_max_sdu_size field.  This means that
   // although the client sends 100000 bytes at once, the server
   // will receive them in packets the size of fwd_max_sdu_size.
   bzero( aal_parm, sizeof(aal_parm_t) );
   aal_parm.length = sizeof(aal_5_t);
   aal_parm.aal_type = CM_AAL_5;
   aal_parm.aal_info.aal5.fwd_max_sdu_size = 7708;
   aal_parm.aal_info.aal5.bak_max_sdu_size = 7520;
   aal_parm.aal_info.aal5.mode = CM_MESSAGE_MODE;
   aal_parm.aal_info.aal5.sscs_type = CM_NULL_SSCS;
   error = setsockopt( s, 0, SO_ATM_AAL_PARM, (void *)&aal_parm,
                       sizeof(aal_parm_t) );
   if (error) {
      perror("setsockopt SO_AAL_PARM");
      exit(-1);
   } /* endif */
   // Up to three BLLI may be specified in the setup message.
   // If a BLLI contains valid information, its length must be
   // set to sizeof(blli_t).  Otherwise set its length to 0.
   // In this example the application specifies two BLLIs.
   // After the connection has been established, the application
   // can use getsockopt to see which BLLI was accepted by the
   // called station.
   bzero(blli, sizeof(blli_t) );
   blli[0].length = sizeof(blli_t);
   blli[1].length = sizeof(blli_t);
   blli[2].length = 0;
   blli[0].L2_prot = CM_L2_PROT_USER;
   blli[0].L2_info = 1;
   // Fields that are not used must be set to NOT_SPECIFIED_B (byte)
   blli[0].L2_mode = NOT_SPECIFIED_B;
   blli[0].L2_win_size = NOT_SPECIFIED_B;
   blli[0].L3_prot = NOT_SPECIFIED_B;
   blli[0].L3_mode = NOT_SPECIFIED_B;
   blli[0].L3_def_pkt_size = NOT_SPECIFIED_B;
   blli[0].L3_pkt_win_size = NOT_SPECIFIED_B;
   blli[0].L3_info = NOT_SPECIFIED_B;
   blli[0].ipi = NOT_SPECIFIED_B;
   blli[0].snap_oui[0] = NOT_SPECIFIED_B;
   blli[0].snap_oui[1] = NOT_SPECIFIED_B;
   blli[0].snap_oui[2] = NOT_SPECIFIED_B;
   blli[0].snap_pid[0] = NOT_SPECIFIED_B;
   blli[0].snap_pid[1] = NOT_SPECIFIED_B;
   // Up to three blli may be specified in the setup message.
   // The caller must query the blli with getsockopt to see which
   // blli the other side accepted.
   blli[1].L2_prot = CM_L2_PROT_USER;
   blli[1].L2_info = 2;
   // Fields that are not used must be set to NOT_SPECIFIED_B (byte)
   blli[1].L2_mode = NOT_SPECIFIED_B;
   blli[1].L2_win_size = NOT_SPECIFIED_B;
   blli[1].L3_prot = NOT_SPECIFIED_B;
   blli[1].L3_mode = NOT_SPECIFIED_B;
   blli[1].L3_def_pkt_size = NOT_SPECIFIED_B;
   blli[1].L3_pkt_win_size = NOT_SPECIFIED_B;
   blli[1].L3_info = NOT_SPECIFIED_B;
   blli[1].ipi = NOT_SPECIFIED_B;
   blli[1].snap_oui[0] = NOT_SPECIFIED_B;
   blli[1].snap_oui[1] = NOT_SPECIFIED_B;
   blli[1].snap_oui[2] = NOT_SPECIFIED_B;
   blli[1].snap_pid[0] = NOT_SPECIFIED_B;
   blli[1].snap_pid[1] = NOT_SPECIFIED_B;
   error = setsockopt( s, 0, SO_ATM_BLLI, (void *)&blli,
                       sizeof(blli) );
   if (error) {
      perror("setsockopt SO_ATM_BLLI");
      exit(-1);
   } /* endif */
   // See ATM UNI 3.0 Appendix xx for details of valid combinations
   // Here we specify a rate enforced 1 Mbps connection.
   traffic.best_effort = FALSE;     // Specifies Rate enforcement
   traffic.fwd_peakrate_lp = 1000;  // Kbps
   traffic.bak_peakrate_lp = 1000;  // Kbps
   traffic.tagging_bak = FALSE;
   traffic.tagging_fwd = FALSE;
   // Fields that are not used must be set to NOT_SPECIFIED_L (long)
   traffic.fwd_peakrate_hp = NOT_SPECIFIED_L;
   traffic.bak_peakrate_hp = NOT_SPECIFIED_L;
   traffic.fwd_sus_rate_hp = NOT_SPECIFIED_L;
   traffic.bak_sus_rate_hp = NOT_SPECIFIED_L;
   traffic.fwd_sus_rate_lp = NOT_SPECIFIED_L;
   traffic.bak_sus_rate_lp = NOT_SPECIFIED_L;
   traffic.fwd_bur_size_hp = NOT_SPECIFIED_L;
   traffic.bak_bur_size_hp = NOT_SPECIFIED_L;
   traffic.fwd_bur_size_lp = NOT_SPECIFIED_L;
   traffic.bak_bur_size_lp = NOT_SPECIFIED_L;
   error = setsockopt( s, 0, SO_ATM_TRAFFIC_DES, (void *)&traffic,
                       sizeof(traffic_des_t) );
   if (error) {
      perror("set traffic");
      exit(-1);
   } /* endif */
   // Set the Broadband Bearer Capability
   // See the UNI 3.0 for valid combinations
   bearer.bearer_class = CM_CLASS_C;
   bearer.traffic_type = NOT_SPECIFIED_B;
   bearer.timing = NOT_SPECIFIED_B;
   bearer.clipping = CM_NOT_SUSCEPTIBLE;
   bearer.connection_cfg = CM_CON_CFG_PTP;
   error = setsockopt( s, 0, SO_ATM_BEARER, (void *)&bearer,
                       sizeof(bearer_t) );
   if (error) {
      perror("set bearer");
      exit(-1);
   } /* endif */
  printf("Input ATM address to be called:\n");
  i = scanf("%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x",
            &o[0], &o[1], &o[2], &o[3], &o[4],
            &o[5], &o[6], &o[7], &o[8], &o[9],
            &o[10], &o[11], &o[12], &o[13], &o[14],
            &o[15], &o[16], &o[17], &o[18], &o[19] );
   if (i != 20) {
      printf("invalid atm address\n");
      exit(-1);
   }
   for (i=0; i<20; i++) {
     addr.sndd_atm_addr.number.addr[i] = o[i];
   } /* endfor */
   addr.sndd_atm_addr.length = ATM_ADDR_LEN;
   addr.sndd_atm_addr.type = CM_INTL_ADDR_TYPE;
   addr.sndd_atm_addr.plan_id = CM_NSAP;
   addr.sndd_atm_addr.pres_ind = NOT_SPECIFIED_B;
   addr.sndd_atm_addr.screening = NOT_SPECIFIED_B;
   addr.sndd_atm_vc_type = CONN_SVC;
   error = connect( s, (struct sockaddr *)&addr, sizeof(addr) );
  if (error) {
      perror("connect");
      // If a connect fails, the cause structure may contain useful
      // information for determining the reason of the failure.
      // See the ATM UNI 3.0 for a description of the cause values.
      size = sizeof(cause_t);
      error = getsockopt(s, 0, SO_ATM_CAUSE, (void *)&cause, &size);
      if (error) {
         perror("SO_ATM_CAUSE");
      } else {
         printf("cause = %d\n", cause.cause );
      } /* endif */
      exit(-1);
   } /* endif */
   // The caller can now check to see which BLLI was accepted by
   // the called station.
   size = sizeof(blli_t);
   error = getsockopt(s, 0, SO_ATM_BLLI,
                         (void *)&blli, &size);
   if (error) {
     perror("get blli");
     exit(0);
   } /* endif */
   printf("The call was accepted by L2_info %d\n", blli[0].L2_info );
   size = sizeof(aal_parm_t);
   error = getsockopt(s, 0, SO_ATM_AAL_PARM,
                               (void *)&aal_parm, &size);
   // If any of these negotiated parameters is unacceptable to
   // the caller, he should disconnect the call by closing the socket.
   printf("fwd       %d\n",
           aal_parm.aal_info.aal5.fwd_max_sdu_size );
   printf("bak       %d\n",
           aal_parm.aal_info.aal5.bak_max_sdu_size );
   // Specifies how many outstanding transmits are allowed before
   // the adapter device driver will return an error.  The error
   // informs the application that it must wait before trying to
   // transmit again.
   max_pend = 2;
   error = setsockopt( s, 0, SO_ATM_MAX_PEND, (void *)&max_pend, 1 );
   if (error) {
     perror("set MAX_PENDING");
     exit(-1);
   } /* endif */
   while (1) {
      error = send( s, buff, BUFF_SIZE, 0 );
      if (error == -1) {
         if (errno == ENOSPC) {
         // The application has reached the maximum outstanding
         // transmits.  It must wait before trying again.
            perror("send");
            sleep(1);
        } else {
            perror("send");
            size = sizeof(cause_t);
            error = getsockopt(s, 0, SO_ATM_CAUSE, (void *)&cause, &size);
            if (error) {
               perror("SO_ATM_CAUSE");
            } else {
               printf("cause = %d\n", cause.cause );
            }
            exit(-1);
         } /* endif */
      } else {
         printf("sent %d\n", error );
      }
   }
}

[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]