__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)

参考一下博客:

http://yaoyang.blog.51cto.com/7657153/1269713

http://blog.csdn.net/eric_liufeng/article/details/10475583

网络驱动接收到报文后,会初始化skb->protocol字段,再通过netif_rx(skb);传输给3层协议,3层协议根据skb->protocol字段决定使用哪个协议实例处理。

某一mac协议类型的全部网络设备都是使用相同的xx_type_trans()函数来获取protocol的:以太网设备驱动调用eth_type_trans(), FDDI网络设备驱动调用fddi_type_trans().

/**
 * eth_type_trans - determine the packet's protocol ID.
 * @skb: received socket data
 * @dev: receiving network device
 *
 * The rule here is that we
 * assume 802.3 if the type field is short enough to be a length.
 * This is normal practice and works for any 'now in use' protocol.
 */
__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
	unsigned short _service_access_point;
	const unsigned short *sap;
	const struct ethhdr *eth;

	skb->dev = dev;
	skb_reset_mac_header(skb);
	//获取第二层数据包的报头
	skb_pull_inline(skb, ETH_HLEN);
	eth = eth_hdr(skb);

	/*
	* 在skb->pkt_type中得到识别和注册
	* PACKET_BROADCAST:广播包 
	* PACKET_MULTICAST:2层组播地址 
	* PACKET_HOST:发送给本机的报文 
	* PACKET_OTHERHOST: 发送给其他主机的报文,这里主机应该处于混杂模式中 
	*/
	if (unlikely(is_multicast_ether_addr(eth->h_dest))) {
		if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
			skb->pkt_type = PACKET_BROADCAST;
		else
			skb->pkt_type = PACKET_MULTICAST;
	}
	else if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
						   dev->dev_addr)))
		skb->pkt_type = PACKET_OTHERHOST;

	/*
	 * 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.
	 */
	if (unlikely(netdev_uses_dsa(dev)))
		return htons(ETH_P_XDSA);

	/*如果长度大于1536(最大帧长度ETH_P_802_3_MIN),那么他是802.3兼容以太网卡,协议字段在eth->h_proto中标识*/  
	if (likely(ntohs(eth->h_proto) >= ETH_P_802_3_MIN))
		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.
	 */
	sap = skb_header_pointer(skb, 0, sizeof(*sap), &_service_access_point);
	if (sap && *sap == 0xFFFF)
		return htons(ETH_P_802_3);

	/*
	 *      Real 802.2 LLC
         * 802.2的协议头返回后,被当做三层报文处理, 
         * 协议处理被散列在ptype_base中,协议处理函数为p8022_rcv() 
         * 对应的三层协议可以通过 register_8022_client() 将自己的处理函数注册到p8022_rcv()中 
         * 如果 register_8022_client(0xAA, snap_rcv)就将SNAP的三层处理函数注册进去了
	 */
	return htons(ETH_P_802_2);
}


猜你喜欢

转载自blog.csdn.net/cityday/article/details/51918942