LaKabane / libtuntap

The portable Tun/Tap devices configuration utility
193 stars 63 forks source link

Can't read from tap interface, stuck in the read api forever #40

Closed seshasaikira closed 10 months ago

seshasaikira commented 1 year ago

We are using a library "libtuntap" to create a virtual network interface. I have created a sample application which will create the interface, read from and write to the interface. I tested this application in Kernel 6.0.0, where it is working fine but however the same application is not working latest kernel 6.1.4 i.e the application is stuck in read() API and is blocked forever.

After deep deubugging I have identified the rootcause that the kernel configuration CONFIG_IPV6 is enabled in kernel 6.0.0 and is disabled in latest kernel 6.1.4 as part of kernel optimization.

Since enabling CONFIG_IPV6 increases the kernel size around 232 KB, we tried to identify & avoid the dependency between Tuntap device & IPV6 configuration, and tried different options, but unfortunately we didn't get any clue. FYI: 1) tap0 interface is created 2) able to se the ipv4 address. but the application is failing in read api.

Q1) Is CONFIG_IPV6 is really needed to make tun/tap library work? Q2) If CONFIG_IPV6 is not needed how to avoid the dependency? Q3) Please suggest if we are missing anything.

I am sharing the sample application code for reference.

include

include

include

include

include

include

include <net/if.h>

include <sys/ioctl.h>

include

define MAX_DATA_ETHFRAME 1520

const uint8_t EOK = 0; const uint8_t ERROR_TUNTAP_INVALID = 1; const uint8_t ERROR_TUNTAP_START = 2; const uint8_t ERROR_TUNTAP_MTU = 2; const uint8_t ERROR_TUNTAP_IFNAME = 4; const uint8_t ERROR_TUNTAP_UP = 5; const uint8_t ERROR_CREATION_FILE = 6; const uint8_t ERROR_TUTTAP_SET_IP = 7;

static bool tuntapInitdone = false; struct device *tuntapInitData = NULL;

int main(void) { uint8_t EthData[MAX_DATA_ETHFRAME]; int16_t numbytes; int16_t index; uint8_t tap_init_error = ERROR_TUNTAP_INVALID; tuntapInitdone = false; int retVal = 0; //Initialize the tap interface tuntapInitData = tuntap_init();

char ipaddr[20] = "172.19.0.4";

do {

//Start the tap interface
    if(tuntap_start(tuntapInitData, TUNTAP_MODE_ETHERNET, 0) != EOK)
    {
        //error condition tuntap init failed
        tap_init_error = ERROR_TUNTAP_START;
    printf("Tun Tap not started .. exiting\n");
        break;
    }

    //set the mtu to 1520 bytes
    if(tuntap_set_mtu(tuntapInitData, MAX_DATA_ETHFRAME) != EOK)
    {
        //error condition tuntap set Mtu failed
        tap_init_error = ERROR_TUNTAP_MTU;
    printf("MTU setup failed .. exiting\n");
        break;
    }

//set the ip address 172.19.0.4
    if(tuntap_set_ip(tuntapInitData, ipaddr, 24) != EOK)
    {
        //error condition tuntap set Mtu failed
        tap_init_error = ERROR_TUTTAP_SET_IP;
    printf("IP setup failed.. exiting\n");
        break;
    }

    if(tuntap_up(tuntapInitData) != EOK)
    {
        //error condition tuntap interface up failed
        tap_init_error = ERROR_TUNTAP_UP;
    printf("Tun tap is not up.. exiting\n");
        break;
    }

    //If tuntap init is successful, so set the init done flag
    tap_init_error = EOK;
    tuntapInitdone = true;
    printf("\tTap interface init done and is up \n");

}while(0);

if(tuntapInitdone == false)
{
    //destroy the interface and free memory
        tuntap_destroy(tuntapInitData);
        printf("\tTap interface init failed and is down : %d\n", tap_init_error);
}

while(1)
{
    //Invoke the TUN/TAP read API
    numbytes = tuntap_read(tuntapInitData,(void*)EthData,sizeof(EthData));

    printf("\tTap Read bytes: %d ",numbytes);
    for (index=0;index<numbytes;index++)
    {
        printf("%02x:",EthData[index]);
    }
    printf("\n\n");

    sleep(2);

    ssize_t written_bytes = tuntap_read(tuntapInitData, (void*)EthData, numbytes);
    if(written_bytes >=0)
    {
        printf("write successful with no of bytes: %d\n", written_bytes);
    }
    else
    {
        printf("Write failed with no of bytes: %d\n", written_bytes);
        printf("cannot write with errno: %d\n", errno);
    }

    sleep(3);       
}

}

Thanks & Regards M. Sesha Saikiran

tleguern commented 11 months ago

Hello @seshasaikira, I was not able to reproduce your problem but I also do not have the same kernel configuration. From the top of my head: do your program has the correct rights to open a tap device?

Regarding your question about IPv6 no it is not needed, especially since I did not merge any of the pull requests implementing this protocol.