multipath-tcp / mptcp

⚠️⚠️⚠️ Deprecated 🚫 Out-of-tree Linux Kernel implementation of MultiPath TCP. 👉 Use https://github.com/multipath-tcp/mptcp_net-next repo instead ⚠️⚠️⚠️
https://github.com/multipath-tcp/mptcp_net-next
Other
889 stars 335 forks source link

Fail to use getsockopt() to get all subflows' info #432

Open KOWKO1 opened 3 years ago

KOWKO1 commented 3 years ago

Hello, When I used getsockopt() to get all subflows' information, it always fails, I can not get all subflows information, I can only get one subflow‘s information . For example, I have 3 subflows(IP1 , IP2, IP3) during connection, but I can only get the last one subflow's(IP3) information(I am sure that all subflows are transferring data ), I don't know the reason of that.

#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 <arpa/inet.h>
#include <time.h>

#include <linux/tcp.h>
#include <linux/mptcp.h>

#define NIC_NUMBER 2 

void print_subflow_info(struct mptcp_info);
int get_fsize(FILE*);

int main(int argc, char** argv)
{
    char* ADDR;
    int PORT;
    char* FILE_PATH;

    int sock;
    struct sockaddr_in addr;
    int ret;

    FILE* file;
    char send_buff[1024] = { '\0', };
    int fsize = 0, nsize = 0;

    int enable = 1;
    int val = MPTCP_INFO_FLAG_SAVE_MASTER;

    char *scheduler = "default";

    struct mptcp_info minfo;
    struct mptcp_meta_info meta_info;
    struct tcp_info initial;
    struct tcp_info others[NIC_NUMBER];
    struct mptcp_sub_info others_info[NIC_NUMBER];
    socklen_t len;

    clock_t start_t, end_t;

    minfo.tcp_info_len = sizeof(struct tcp_info);
    printf("minfo.tcp_info_len is %d\n",minfo.tcp_info_len);

    minfo.sub_len = sizeof(others);
    printf("minfo.sub_len  is %d\n",minfo.sub_len );

    minfo.meta_len = sizeof(struct mptcp_meta_info);
    printf("minfo.meta_len  is %d\n",minfo.meta_len);

    minfo.meta_info = &meta_info;
    minfo.initial = &initial;
    minfo.subflows = others;

    minfo.sub_info_len = sizeof(struct mptcp_sub_info);
    printf("minfo.sub_info_len  is %d\n",minfo.sub_info_len);

    minfo.total_sub_info_len = sizeof(others_info);
    printf("minfo.total_sub_info_len  is %d\n",minfo.total_sub_info_len);

    minfo.subflow_info = others_info;
    len = sizeof(minfo);
    printf("len 2 is %d\n",len);

    if(argc != 4){
        fprintf(stderr, "usage: %s [host_address] [port_number] [file_path]\n", argv[0]);
        return -1;
    }
    ADDR = argv[1];
    PORT = atoi(argv[2]);
    FILE_PATH = argv[3];

    /* create socket */
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0){
        perror("[client] socket() ");
        return -1;
    }

    ret = setsockopt(sock, 6, MPTCP_ENABLED, &enable, sizeof(int));
    if(ret < 0){
        perror("[client] setsockopt(MPTCP_ENABLED) ");
        return -1;
    }

    ret = setsockopt(sock, 6 ,MPTCP_SCHEDULER, scheduler, strlen(scheduler));
    if(ret < 0){
        perror("[client] setsockopt(MPTCP_SCHEDULER) ");
        return -1;
    }

    ret = setsockopt(sock, IPPROTO_TCP, MPTCP_INFO, &val, sizeof(val));
    if(ret < 0){
        perror("[client] setsockopt(MPTCP_INFO) ");
        return -1;
    }

    memset(&addr, 0x00, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ADDR);
    addr.sin_port = htons(PORT);

    ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
    if(ret < 0){
        perror("[client] connect() ");
        return -1;
    }
    printf("[client] connected\n");

    file = fopen(FILE_PATH, "rb");
    if(file == NULL){
        perror("[client] fopen() ");
        return -1;
    }

    fsize = get_fsize(file);

    start_t = clock();
    printf("[client] sending file...(%s)\n", FILE_PATH); 
    while(nsize!=fsize){
        int fpsize = fread(send_buff, 1, 1024, file);
        nsize += fpsize;
        send(sock, send_buff, fpsize, 0);

        if(getsockopt(sock, IPPROTO_TCP, MPTCP_INFO, &minfo, &len)<0){
          printf("error getopt....\n");

        }

        print_subflow_info(minfo);

        end_t = clock();

    }
    printf("[client] finished\n");
    fclose(file);
    close(sock);

    return 0;
}

void print_subflow_info(struct mptcp_info minfo)
{
    int subflows_info_len = minfo.total_sub_info_len;
    int subflows_number = subflows_info_len / sizeof(struct mptcp_sub_info);
    int i;

    printf("-----------------------\n");
    printf("[subflows number] %d\n", subflows_number);
    for(i=0; i<subflows_number; i++){
            FILE *fp = fopen("./log.txt","a+");
        printf("[subflow %d] %s:%d ", i, inet_ntoa(minfo.subflow_info[i].src_v4.sin_addr), ntohs(minfo.subflow_info[i].src_v4.sin_port));
        printf("-> %s:%d", inet_ntoa(minfo.subflow_info[i].dst_v4.sin_addr), ntohs(minfo.subflow_info[i].dst_v4.sin_port));

            printf("  { rto %d, ato %d , rtt %d, snd_mss %d, rcv_mss %d, total_retrans %d }\n", 
                minfo.subflows[i].tcpi_rto,
                minfo.subflows[i].tcpi_ato, 
                minfo.subflows[i].tcpi_rtt, 
                minfo.subflows[i].tcpi_snd_mss, 
                minfo.subflows[i].tcpi_rcv_mss, 
                minfo.subflows[i].tcpi_total_retrans ); 
                //printf("[subflow %d] %s:%d ", i, inet_ntoa(minfo.subflow_info[i].src_v4.sin_addr), ntohs(minfo.subflow_info[i].src_v4.sin_port));

        fprintf(fp,"[subflow %d] %s:%d ", i, inet_ntoa(minfo.subflow_info[i].src_v4.sin_addr), ntohs(minfo.subflow_info[i].src_v4.sin_port));
        fprintf(fp,"-> %s:%d", inet_ntoa(minfo.subflow_info[i].dst_v4.sin_addr), ntohs(minfo.subflow_info[i].dst_v4.sin_port));

            fprintf(fp,"  { rto %d, ato %d , rtt %d, snd_mss %d, rcv_mss %d, total_retrans %d }\n", 
                minfo.subflows[i].tcpi_rto,
                minfo.subflows[i].tcpi_ato, 
                minfo.subflows[i].tcpi_rtt, 
                minfo.subflows[i].tcpi_snd_mss, 
                minfo.subflows[i].tcpi_rcv_mss, 
                minfo.subflows[i].tcpi_total_retrans ); 
        fclose(fp);
    }

}

int get_fsize(FILE* file)
{
    int fsize;

    fseek(file, 0, SEEK_END);
    fsize=ftell(file);
    fseek(file, 0, SEEK_SET);   

    return fsize;
}
matttbe commented 3 years ago

Hi @KOWKO1

Thank you for the bug report. Here are a few questions:

Do not hesitate to print the output of a getsockopt(..., MPTCP_ENABLED, ...); just to make sure your connection didn't fallback to TCP.