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
888 stars 335 forks source link

Failed to use getsockopt #409

Closed cxht closed 3 years ago

cxht commented 3 years ago

Hi, I move my problem from issue #393.
When I called getsockopt(), it always fail and return -1. I don't know the reason of that. My client code is here:

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <linux/tcp.h>
#include <stdio.h>
#include <errno.h>
#include<string.h>
#define MPTCP_INFO_FLAG_SAVE_MASTER 0x01
int main()
{
    struct mptcp_info minfo;
    struct mptcp_meta_info meta_info;
    struct tcp_info initial;
    struct tcp_info others[3];
    struct mptcp_sub_info others_info[3];
    int val = MPTCP_INFO_FLAG_SAVE_MASTER;
    minfo.tcp_info_len = sizeof(struct tcp_info);
    minfo.sub_len = sizeof(others);
    minfo.meta_len = sizeof(struct mptcp_meta_info);
    minfo.meta_info = &meta_info;
    minfo.initial = &initial;
    minfo.subflows = &others;
    minfo.sub_info_len = sizeof(struct mptcp_sub_info);
    minfo.total_sub_info_len = sizeof(others_info);
    minfo.subflow_info = &others_info;    
    int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sockfd == -1)
        printf("\nsocket error");
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET;            
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    serv_addr.sin_port = htons(8080);
    char pathmanager[] = "fullmesh";
    int a =setsockopt(sockfd, 6, MPTCP_PATH_MANAGER, pathmanager, sizeof(pathmanager));
    char scheduler[] = "roundrobin";
    a = setsockopt(sockfd, 6, MPTCP_SCHEDULER, scheduler, sizeof(scheduler));
    printf("\nsch a=%d",a);
    a= connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    if(a<0)
    {
        printf("connect err\n");
        exit(0);
    }
    a= setsockopt(sockfd, 6, MPTCP_INFO, &val, sizeof(val));
    printf("\n save master=%d",a);
    int m = getsockopt(sockfd, 6, MPTCP_INFO, &minfo, sizeof(minfo));
    if(m==-1)
    {
        printf("\ncannot getsockopt(MPTCP_INFO)");
        printf("\nerrno =%d: %s\n",errno, strerror(errno));
    }
    printf("bytes:%d\nuna:%d\nrtt:%d\n",minfo.initial->tcpi_bytes_sent,minfo.initial->tcpi_unacked,minfo.initial->tcpi_rtt);
    char sendbuf[1024];
    char recvbuf[1024];
    FILE *f ;
    f=fopen("random","r");
    while(fgets(sendbuf, sizeof(sendbuf), f) > 0)
    {
        send(sockfd, sendbuf, strlen(sendbuf),0); 
        if(strcmp(sendbuf,"exit\n")==0)
            break;
        recv(sockfd, recvbuf, sizeof(recvbuf),0); 
        //fputs(recvbuf, stdout);
        memset(sendbuf, 0, sizeof(sendbuf));
        memset(recvbuf, 0, sizeof(recvbuf));
    }
    close(sockfd);
    close(f);
    return 0;
}

All answers of your questions are attached here:

Thanks for your reply.

matttbe commented 3 years ago

Hello,

What's the errno value? (number + message)

A:Errno : 14 Bad address

If you have this error, it likely means your userspace program didn't provide enough space to the kernel to write info. Not sure why, it looks OK but something to check (sizeof OK? Maybe taking a wrong structure?) Do you have many subflows?

Which command are you using to compile this code?

A: My compile code is gcc client.c -o client -I mptcp/include/generated/uapi/ -I mptcp/include/uapi/ -I mptcp/include/

If you compiled the kernel code by yourself, I think you are supposed to run make headers_install from the kernel dir and only use the generated dir for the include I think: -I mptcp/usr/include/.

Do you have warnings when compiling the code?

serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

Likely, this connection is not going to use MPTCP. Maybe that's something to look at but it should not cause a EFAULT errno.

cxht commented 3 years ago

@matttbe
I have no idea of what's wrong with the minfo structure, and I have 3 subflows during connection. I will have a try to make headers_install. After I read the man page of getsockopt(), I find it needs to pass a pointer as the last parameter. So I try to pass a pointer such as:

int len_minfo = sizeof(minfo);
getsockopt(sockfd,6,MPTCP_INFO,&minfo,&len_minfo);

I also try to use getsockopt() to get TCP_INFO, MPTCP_SCHEULER and MPTCP_PATH_MANAGER, all of them are correct, but getting MPTCP_INFO still have error, the errno value has change to 22:invalid argument.

matttbe commented 3 years ago

Mmh yes indeed, I didn't see that, you should use a pointer.

Were there any warnings from your compiler about that? Are there still others?

You should also use socklen_t instead of int for len_minfo.

You can get EINVAL (22, invalid argument) if you use it with a non MPTCP connection (e.g. fallback to TCP). If you use a localhost connection, that's likely the case.

You could also have it if the initial subflow has been removed, you ask to have it (minfo.initial != NULL) and you didn't set MPTCP_INFO_FLAG_SAVE_MASTER.

cxht commented 3 years ago

@matttbe The return value of getsockopt MPTCP_INFO is 0 now. I build a multipath environment in mininet to replace the localhost connection, and set the last parameter to socklen_t len_minfo = sizeof(minfo); getsockopt(sockfd, 6, MPTCP_INFO, &minfo, &len_minfo);. Now it works with no error. Thank you very much!

matttbe commented 3 years ago

Great, we can close this one then!