Stream Control Transmission Protocol (SCTP) Associations
In TCP, a stream is just a sequence of bytes. In SCTP, it has a different meaning; a stream is a logical channel along which messages are sent, and a single association can have many streams. The original motivation for streams came from the telephony domain, where multiple reliable channels were needed, but the messages on each channel were independent of those on other channels. In last month's article, we pointed out some TCP applications that could benefit from streams, such as FTP, which uses two sockets for data and control messages. In addition, an increasing number of applications are multithreaded, and streams open up the possibility of a thread in one peer being able to communicate with a thread in another peer without worrying about being blocked by messages sent by other threads.
The socket I/O calls read/write/send/recv do not know about SCTP streams. By default, the write calls all use stream number zero (this can be changed by a socket option), but the read calls will read messages on all streams, and there is no indication as to which stream is used. So, to use streams effectively, you need to use some of the I/O calls that are designed specifically for SCTP.
Each endpoint of an association will support a certain number of streams. A Linux endpoint, by default, will expect to be able to send to ten streams, while it can receive on 65,535 streams. Other SCTP stacks may have different default values. These values can be changed by setting the socket option SCTP_INITMSG, which takes a structure sctp_initmsg:
struct sctp_initmsg {
uint16_t sinit_num_ostreams;
uint16_t sinit_max_ostreams;
uint16_t sinit_max_attempts;
uint16_t sinit_max_init_timeo;
}
If this socket option is used to set values, it must be done before an association is made. The parameters will be sent to the peer endpoint during association initialisation.
Each endpoint in an association will have an idea of how many input and output streams it will allow on an association, as discussed in the previous paragraph. During the establishment of the association, the endpoints exchange these values. Negotiation of final values is just a matter of taking the minimum values. If one end wants 20 output streams, and the other wants only 10 input streams, the result is the smaller, 10, and similarly for the number of streams in the opposite direction.
An endpoint will need to know how many output streams are available for writing in order not to exceed the limits. This value is determined during association setup. After setup, the endpoint can find this by making a query using getsockopt(). However, there is a little wrinkle here: a socket may have many associations (to different endpoints), and each association may have set different values. So, we have to make a query that asks for the parameters for a particular association, not just for the socket. The parameter to ask for is SCTP_STATUS, which takes a structure of type sctp_status:
struct sctp_status {
sctp_assoc_t sstat_assoc_id;
int32_t sstat_state;
uint32_t sstat_rwnd;
uint16_t sstat_unackdata;
uint16_t sstat_penddata;
uint16_t sstat_instrms;
uint16_t sstat_outstrms;
uint32_t sstat_fragmentation_point;
struct sctp_paddrinfo sstat_primary;
};
This has fields sstat_instrms and sstat_outstrms, which contain the required information. See Listings 2 and 3 for a client and server negotiating the number of streams in each direction.
Listing 2. streamcount_echo_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#define ECHO_PORT 2013
char *usage_msg = "usage: astreamcount_echo_client ip-addr istreams
ostreams";
char *msg = "hello";
void usage() {
fprintf(stderr, "%s\n", usage_msg);
exit(1);
}
int main(int argc, char *argv[]) {
int sockfd;
int len;
struct sockaddr_in serv_addr;
int port = ECHO_PORT;
struct sctp_initmsg initmsg;
struct sctp_status status;
if (argc != 4) usage();
/* create endpoint */
sockfd = socket(AF_INET, SOCK_STREAM,
IPPROTO_SCTP
);
if (sockfd < 0) {
perror("socket creation");
exit(2); }
/* connect to server */
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(port);
memset(&initmsg, 0, sizeof(initmsg));
initmsg.sinit_max_instreams = atoi(argv[2]);
initmsg.sinit_num_ostreams = atoi(argv[3]);
printf("Asking for: input streams: %d, output streams: %d\n",
initmsg.sinit_max_instreams,
initmsg.sinit_num_ostreams);
if (setsockopt(sockfd, IPPROTO_SCTP,
SCTP_INITMSG, &initmsg, sizeof(initmsg))) {
perror("set sock opt\n");
}
if (connect(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
perror("connectx");
exit(3);
}
len = sizeof(status);
memset(&status, 0, len);
if (getsockopt(sockfd, IPPROTO_SCTP,
SCTP_STATUS, &status, &len) == -1) {
perror("get sock opt");
}
printf("Got: input streams: %d, output streams: %d\n",
status.sstat_instrms,
status.sstat_outstrms);
/* give the server time to do something */
sleep(2);
/* no reads/writes are done */
close(sockfd);
exit(0);
}
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- RSS Feeds
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- A Topic for Discussion - Open Source Feature-Richness?
- Drupal Is a Framework: Why Everyone Needs to Understand This
- Home, My Backup Data Center
- New Products
- Paranoid Penguin - Building a Secure Squid Web Proxy, Part IV
- Developer Poll
- Trying to Tame the Tablet
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




35 min 10 sec ago
4 hours 48 min ago
7 hours 21 min ago
12 hours 34 sec ago
14 hours 23 min ago
1 day 7 hours ago
1 day 9 hours ago
1 day 11 hours ago
1 day 11 hours ago
1 day 11 hours ago