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]; // Temorary 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 );
}
}
}