There are several types of Ethernet frames:
- Ethernet II frame, or Ethernet Version 2,[f] or
DIX frame is the most common type in use today, as it is often used directly by the Internet Protocol.(太网帧) - Novell raw IEEE
802.3 non-standard variation frame - IEEE 802.2 Logical
Link Control (LLC) frame - IEEE 802.2 Subnetwork
Access Protocol (SNAP) frame - 不同的帧有不同的格式和MTU值
上图中表示各个帧的数据格式。
下面是通用Ethernet II 帧示意图
带有vlan tag的以太网帧。通常MAC层的ethernet帧是指ethernnet II的帧
图中的vlan tag是可选项,指对vlan接口有意义。下面是VLAN的具体介绍:
下图是用户数据从最上层到MAC层的封装示意图
以太网的硬件地址长度为48 bits(6 字节),而L2数据帧有三种类型:单播,多播和广播,其中广播可看作多播的一种特殊情况。Bit 0用于表示多播还是单播,当bit 0为1时,为多播,为0时,表示单播。
Linux kernel使用eth_type_trans来判断数据帧的类型,及协议类型。
__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) { struct ethhdr *eth; skb->dev = dev; skb_reset_mac_header(skb); skb_pull_inline(skb, ETH_HLEN); eth = eth_hdr(skb); if (unlikely(is_multicast_ether_addr(eth->h_dest))) { /* 如果是多播地址,即bit0为1*/ if (!compare_ether_addr_64bits(eth->h_dest, dev->broadcast)) skb->pkt_type = PACKET_BROADCAST; //与设备的广播地址相同,则帧为广播帧 else skb->pkt_type = PACKET_MULTICAST; //与设备的广播地址不同,则帧为多播帧 } /* * This ALLMULTI check should be redundant by 1.4 * so don't forget to remove it. * * Seems, you forgot to remove it. All silly devices * seems to set IFF_PROMISC. */ /* 这里为什么不检测IFF_PROMISC标志呢? 我怀疑是因为有的网卡不设置这个标志,依然可以收到不属于自己地址的数据包 */ else if (1 /*dev->flags&IFF_PROMISC */ ) { /* 如果数据帧的目的地址不是网卡的地址,那么数据帧的类型为PACKET_OTHERHOST */ if (unlikely(compare_ether_addr_64bits(eth->h_dest, dev->dev_addr))) skb->pkt_type = PACKET_OTHERHOST; /* 默认情况,skb->pkt_type为0,即PACKET_HOST,即数据帧是发给本主机的 */ } /* 下面开始判断L2协议 */ /* * Some variants of DSA tagging don't have an ethertype field * at all, so we check here whether one of those tagging * variants has been configured on the receiving interface, * and if so, set skb->protocol without looking at the packet. */ /* 如上面的注释所说,当设备指定了DSA或者TRAILER,那么就不需要检查包,直接返回DSA或者TRAILER */ if (netdev_uses_dsa_tags(dev)) return htons(ETH_P_DSA); if (netdev_uses_trailer_tags(dev)) return htons(ETH_P_TRAILER); /* 当协议值大于136时,那么这个数据帧一定为ethernet frame 因为802.2和802.3的对应域为帧长,均要小于或等于1500,而ethernet frame的协议类型都大于等于1536. */ if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; /* * This is a magic hack to spot IPX packets. Older Novell breaks * the protocol design and runs IPX over 802.3 without an 802.2 LLC * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This * won't work for fault tolerant netware but does for the rest. */ /* 当IPX使用原始的802.3作为载体时,其头两个字节作为checksum,但是一般都设为0xffff。 */ if (skb->len >= 2 && *(unsigned short *)(skb->data) == 0xFFFF) return htons(ETH_P_802_3); /* * Real 802.2 LLC */ /* ok, 那么类型为802.2*/ return htons(ETH_P_802_2); }