per packet QoS (DSCP)

Discussion in 'Linux Networking' started by aapocketz, Dec 8, 2008.

  1. aapocketz

    aapocketz Guest

    My application calls for sending different UDP packets with different
    QoS priority, using DSCP. To do this I wanted to modify the ToS byte
    in the IP header (bits 8-15 of the IPv4 header) on a per packet
    basis.

    It appears that this is possible using "ancillary data" and sendmsg/
    recvmsg() API and the cmsg routines (http://manpages.ubuntu.com/
    manpages/intrepid/man3/cmsg.html) to modify the header fields.

    I cannot get this to work. Can anyone provide an example that does?
    I am using ubuntu 8.10 and I have tried several things. Here is a
    current little test client. Looking at wireshark I do not see any
    changes to the TOS field (stays zero no matter what). I even tried
    changing things like TTL field without any luck either. Any ideas?

    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <string>
    #include <string.h>


    #define BUFLEN 512
    #define NPACK 10
    #define PORT 9930

    void diep(const char *s) {
    perror(s);
    exit(1);
    }


    #define SRV_IP "127.0.0.1"
    /* diep(), #includes and #defines like in the server */

    int main(void) {
    sockaddr_in si_other = {0};
    msghdr msg = {0};
    int s, i;
    char buf[BUFLEN];

    if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    diep("socket");

    si_other.sin_family = AF_INET;
    si_other.sin_port = htons(PORT);
    if (inet_aton(SRV_IP, &si_other.sin_addr) == 0) {
    fprintf(stderr, "inet_aton() failed\n");
    exit(1);
    }

    for (i = 0; i < NPACK; i++) {
    printf("Sending packet %d\n", i);
    sprintf(buf, "This is packet %d\n", i);
    //if (sendto(s, buf, BUFLEN, 0, (sockaddr *)&si_other, slen) == -1)
    // diep("sendto()");

    // sets the address to send to
    msg.msg_name = &si_other;
    msg.msg_namelen = sizeof(si_other);

    iovec iov[1];
    msg.msg_iov = iov ;
    msg.msg_iovlen = 1;
    int test = 0xEFBEADDE;

    iov[0].iov_base = &test;
    iov[0].iov_len = sizeof test;


    // sets the control ancillary data
    cmsghdr * cmsg;
    //int tos = 0xBEBAFECA; // set to low delay
    int tos = 6; // set to low delay

    char buf[CMSG_SPACE(sizeof(tos))];
    msg.msg_control = buf;
    msg.msg_controllen = sizeof(buf);

    cmsg = CMSG_FIRSTHDR(&msg); // set to first header
    if(cmsg == NULL)
    {
    fprintf(stderr, "CMSG_FIRSTHDR FAILED");
    exit(1);
    }
    // first header is the TOS header
    cmsg->cmsg_level = IPPROTO_IP;
    cmsg->cmsg_type = IP_TOS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(tos));
    *((int *) CMSG_DATA(cmsg)) = tos;
    //void * data = CMSG_DATA(cmsg); // set the data
    //memcpy(data, (void*) &tos, sizeof(tos));
    msg.msg_controllen = cmsg->cmsg_len;

    if (sendmsg(s, &msg, 0) < 0)
    diep("sendmsg()");
    }

    close(s);
    return 0;
    }
     
    aapocketz, Dec 8, 2008
    #1
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.