gpt4 book ai didi

sockets - Linux套接字: why is the ethernet MTU a limit even when transmitting over 802. 11?

转载 作者:行者123 更新时间:2023-12-03 12:08:11 26 4
gpt4 key购买 nike

使用 RAW 和 SOCK_DRAM 编写程序时UDP 套接字,我注意到以太网最大传输单元始终表示我可以发送的数据的限制而不会产生碎片,即使套接字严格绑定(bind)到无线接口(interface)(使用 bind() )并且数据包总是被传输使用 Wi-Fi (802.11) 进行广播,中间没有任何有线网段。

我知道 802.11 MTU 为 2346 B(正确吗?),大于 1500 B。但如果我尝试传输超过以太网 MTU 大小(1500 B),则在使用 UDP 套接字和“使用 errno 90 时出现“消息太大”错误(EMSGSIZEsendto())在 RAW 套接字上。

这是因为从用户应用程序的角度来看,802.11 数据包被视为 802.3 数据包,然后在内核和硬件设备内部进行转换和管理?为什么即使我可以使用“Wi-Fi”传输更大的帧,这个限制仍然适用?

编辑:重现 RAW 套接字问题的示例代码

这是从原始代码中提取的示例代码,您可以使用 gcc 进行编译并用于重现我之前描述的问题。

当使用 RAW 套接字时,超过 1500 B 的消息被明确拒绝,设置 errno ,即使套接字绑定(bind)到无线接口(interface)。

这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/wireless.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/ioctl.h>

#define DEVNAME "wlp2s0"
#define DESTINATIONMAC_INITIALIZER {0x9C,0xD2,0x1E,0x20,0x91,0xE5}

#define SIZEOK 1500
#define SIZEWRONG 1501

int main (int argc, char **argv) {
// wlanLookup() variables, for interface name, source MAC address and return value
char devname[]=DEVNAME;
int ifindex;

int descriptor; // Socket descriptor
struct sockaddr_ll addrll; // sockaddr_ll address structure

struct ifreq wifireq;

struct ether_header etherHeader;

unsigned char bufferok[SIZEOK];
unsigned char bufferwrong[SIZEWRONG];

unsigned char *packetok=NULL;
unsigned char *packetwrong=NULL;

// Source and destination MAC addresses
unsigned char macsrc[6];
unsigned char macdst[6]=DESTINATIONMAC_INITIALIZER;

// Size variables
int sentbytes;
size_t sizeok_final=sizeof(struct ether_header)+SIZEOK; // Size of the ok buffer + size of struct ether_header
size_t sizewrong_final=sizeof(struct ether_header)+SIZEWRONG; // Size of the ok buffer + size of struct ether_header

if(SIZEWRONG<SIZEOK) {
fprintf(stderr,"Error: in this sample code, SIZEWRONG (%d) must be >= than SIZEOK (%d)\n",SIZEWRONG,SIZEOK);
exit(EXIT_FAILURE);
}

descriptor=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));

if(descriptor==-1) {
perror("socket() error");
exit(EXIT_FAILURE);
}

// Get interface index of the interface
strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
if(ioctl(descriptor,SIOCGIFINDEX,&wifireq)!=-1) {
ifindex=wifireq.ifr_ifindex;
} else {
perror("ioctl() error");
close(descriptor);
exit(EXIT_FAILURE);
}

fprintf(stdout,"Using interface: %s (index: %x)\n",DEVNAME,ifindex);

// Prepare sockaddr_ll structure
memset(&addrll,0,sizeof(addrll));
addrll.sll_ifindex=ifindex;
addrll.sll_family=AF_PACKET;
addrll.sll_protocol=htons(ETH_P_ALL);

// Bind to the wireless interface
if(bind(descriptor,(struct sockaddr *) &addrll,sizeof(addrll))<0) {
perror("Cannot bind to interface: bind() error");
close(descriptor);
exit(EXIT_FAILURE);
}

fprintf(stdout,"Bound to interface: %s (index: %x)\n",DEVNAME,ifindex);

// Populate both buffers with some data
for(int i=0;i<SIZEWRONG;i++) {
if(i<SIZEOK) {
bufferok[i]=(unsigned char) (i & 15); // Fill each byte with a cyclic sequence 0x00, 0x01, 0x02, ... 0x0F, 0x00, 0x01, ...
}
bufferwrong[i]=(unsigned char) (i & 15);
}

// Get source MAC address
strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
if(ioctl(descriptor,SIOCGIFHWADDR,&wifireq)!=-1) {
memcpy(macsrc,wifireq.ifr_hwaddr.sa_data,6);
} else {
perror("Cannot get source MAC address: ioctl() error");
close(descriptor);
}
fprintf(stdout,"Source MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",macsrc[0],macsrc[1],macsrc[2],macsrc[3],macsrc[4],macsrc[5]);
fprintf(stdout,"Destination MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",macdst[0],macdst[1],macdst[2],macdst[3],macdst[4],macdst[5]);

// Fill struct ether_header
memcpy(etherHeader.ether_dhost,macdst,ETHER_ADDR_LEN);
memcpy(etherHeader.ether_shost,macsrc,ETHER_ADDR_LEN);
// Using local experimental ethertype for the sake of this sample code, but the effect is the same for any other EtherType
etherHeader.ether_type=htons(0x88B5);

packetok=malloc(sizeok_final*sizeof(unsigned char));
if(!packetok) {
perror("malloc() error");
close(descriptor);
exit(EXIT_FAILURE);
}
packetwrong=malloc(sizewrong_final*sizeof(unsigned char));

if(!packetwrong) {
perror("malloc() error");
free(packetok);
close(descriptor);
exit(EXIT_FAILURE);
}

// Generate the complete packet buffers
// Packet OK
memcpy(packetok,&etherHeader,sizeof(struct ether_header));
memcpy(packetok+sizeof(struct ether_header),bufferok,sizeok_final);

// Packet WRONG
memcpy(packetwrong,&etherHeader,sizeof(struct ether_header));
memcpy(packetwrong+sizeof(struct ether_header),bufferwrong,sizewrong_final);

sentbytes=sendto(descriptor,packetok,sizeok_final,0,(struct sockaddr *)&addrll,sizeof(struct sockaddr_ll));

perror("Packet OK errors (if any)");
fprintf(stdout,"Packet OK: sent %d bytes.\n",sentbytes);

sentbytes=sendto(descriptor,packetwrong,sizewrong_final,0,(struct sockaddr *)&addrll,sizeof(struct sockaddr_ll));

perror("Packet WRONG errors (if any)");
fprintf(stdout,"Packet WRONG: sent %d bytes.\n",sentbytes);

close(descriptor);

return 0;
}

编译前应设置 DEVNAME示例程序应绑定(bind)的接口(interface)名称和 DESTINATIONMAC_INITIALIZER到您要尝试向其发送数据包的目标设备。

我实际上得到了这个输出(在使用 sudo 运行程序之后),显示了超过 1500 B 的数据包是如何被拒绝的:
Using interface: wlp2s0 (index: 3)
Bound to interface: wlp2s0 (index: 3)
Source MAC address: 00:16:ea:4a:bd:7e
Destination MAC address: 9c:d2:1e:20:91:e5
Packet OK errors (if any): Success
Packet OK: sent 1514 bytes.
Packet WRONG errors (if any): Message too long
Packet WRONG: sent -1 bytes.

启动示例程序 3 次后,“ok”数据包被目标设备正确接收,而所有“错误”数据包均未:
Wireshark capture screenshot

非常感谢您提前。

最佳答案

这个问题最终被 LinuxQuestions 的用户解决了。 .

我实际上混淆了 的概念。协议(protocol) MTU 之一接口(interface) MTU .

限制通过 Wi-Fi 传输的帧大小实际上是为相应接口(interface)设置的 MTU,可以通过使用更改,如 LinuxQuestions 中所报告的,ip link set <dev> mtu <mtu> .如果硬件实际支持指定的 MTU,则此命令可以成功,如果硬件不支持,则此命令会失败。

通过增加无线接口(interface)的 MTU 设置,我能够通过 Wi-Fi 成功传输更大的帧,直到最大值 2304 B。

相反,如果我尝试设置更大的接口(interface) MTU,则会收到以下错误,这在某种程度上是意料之中的:

$ sudo ip link set wlp1s0 mtu 2305
Error: mtu greater than device maximum.

最后一点,可以通过以下方式检查每个事件接口(interface)的当前设置的接口(interface) MTU:
ifconfig | grep -i MTU

关于sockets - Linux套接字: why is the ethernet MTU a limit even when transmitting over 802. 11?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54438703/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com