Linux中VLAN功能

  • Post author:
  • Post category:linux




Linux中VLAN功能



1、在linux系统中,VLAN功能实现

(1) 加载8021q模块

在Ubuntu中需用如下命令加载该模块:modprobe 8021q

在嵌入式linux中需在内核中加入8021q支持选项(Networking support -> Networking options ->802.1Q/802.1ad VLAN Support ),如编译成ko,则需手动加载8021q.ko驱动模块;

lsmod | grep 8021q //查询驱动模块;

(2) 建立VLAN虚拟网卡,在eth0网卡下加入子网络,例如命令如下:

ip link add link eth0 name eth0.20 type vlan id 20 //添加子网络;

ip link del eno1.20 //删除子网络



2、二层VLAN数据包的获取

在Linux系统中,建立socket无法直接获取二层网络数据包中带VLAN ID的数据包,但是可以通过sockopt函数设置PACKET_AUXDATA选项,将VLAN信息带上,提取,然后组成802.1q协议包,从而完成802.1q协议VLAN数据包的获取。

设置PACKET_AUXDATA选项:

    int nOptLen = 1;
    if( setsockopt( fd, SOL_PACKET, PACKET_AUXDATA, &nOptLen, sizeof( nOptLen ) ) < 0 )
    {
        perror( "setsockopt PACKET_AUXDATA fail!" );
        close( fd );
        return -1;        
    }

接收带VLAN信息数据:

    struct msghdr msg;
    struct iovec iov;
    struct sockaddr_in Recver_addr;
    struct tpacket_auxdata *aux_ptr;
    struct cmsghdr *cmsg_ptr;
    
    union
    {
        struct cmsghdr  cmsg;
        char buf[CMSG_SPACE( sizeof( struct tpacket_auxdata ) )];
    }cmsg_buf;    

    iov.iov_base = cnRxBuf;
    iov.iov_len = 2000;
    
    msg.msg_name = &Recver_addr;
    msg.msg_namelen = sizeof( Recver_addr );
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = &cmsg_buf;
    msg.msg_controllen = sizeof( cmsg_buf );;
    msg.msg_flags = 0;

...
            nLen = recvmsg( Layer2EthFd, &msg, 0 );
            if( nLen <= 0 ) continue;
            for( cmsg_ptr = CMSG_FIRSTHDR( &msg ); cmsg_ptr; cmsg_ptr = CMSG_NXTHDR( &msg, cmsg_ptr ) )
            {
//                if( cmsg_ptr->cmsg_type != PACKET_AUXDATA ) continue;
                aux_ptr = ( struct tpacket_auxdata * )CMSG_DATA( cmsg_ptr );
//                printf( "  tpid: %04x, tci: %04x\n", aux_ptr->tp_vlan_tpid, aux_ptr->tp_vlan_tci );
                if( 0x8100 == aux_ptr->tp_vlan_tpid )
                {
                    memcpy( cnVlanBuf, cnRxBuf, 12 );
                    cnVlanBuf[12] = aux_ptr->tp_vlan_tpid >> 8;
                    cnVlanBuf[13] = aux_ptr->tp_vlan_tpid & 0x00FF;
                    cnVlanBuf[14] = aux_ptr->tp_vlan_tci >> 8;
                    cnVlanBuf[15] = aux_ptr->tp_vlan_tci & 0x00FF;
                    memcpy( &cnVlanBuf[16], &cnRxBuf[12], nLen - 12 );
                    nLen += 4;
                    write( Layer2EnsFd, cnVlanBuf, nLen );
                    continue;
                }
            }



版权声明:本文为zwenqian0602原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。