目录
- 1. 申明
- 2. 目的
- 3. 背景知识
- 3.1 Ethernet协议的作用和历史
- 3.2 Ethernet承载IP的例子
- 4. 代码demo
- 5. 专栏知识链接
- 6. 写在最后
1. 申明
本文章属于原创,其中参考的代码及文章在结尾处标明,侵删。
2. 目的
本文是为了解析Ethernet协议及其上层承载的协议所写demo。
3. 背景知识
3.1 Ethernet协议的作用和历史
- 以太网是使用最广泛的局域网技术。由于其简单、成本低、可扩展性强、与IP网能够很好地结合等特点,以太网技术的应用正从企业内部网络向公用电信网领域迈进。以太网接入是指将以太网技术与综合布线相结合,作为公用电信网的接入网,直接向用户提供基于IP的多种业务的传送通道。以太网技术的实质是一种二层的媒质访问控制技术,可以在五类线上传送,也可以与其它接入媒质相结合,形成多种宽带接入技术。以太网与电话铜缆上的VDSL相结合,形成EoVDSL技术;与无源光网络相结合,产生EPON技术;在无线环境中,发展为WLAN技术。
- 以太网技术作为数据链路层的一种简单、高效的技术,以其为核心,与其它物理层技术相结合,形成以太网技术接入体系。EoVDSL方式结合了以太网技术和VDSL技术的特点,与ADSL和(五类线上的)以太网技术相比,具有一定的潜在优势。WLAN技术的应用不断推广,EPON技术的研究开发正取得积极进展。随着上述“可运营、可管理”相关关键技术问题的逐步解决,以太网技术接入体系将在宽带接入领域得到更加广泛的应用。
- 同时,以太网技术的应用正在向城域网领域扩展。IEEE802.17RPR技术在保持以太网原有优点的基础上,引入或增强了自愈保护、优先级和公平算法、OAM等功能,是以太网技术的重要创新。对以太网传送的支持,成为新一代SDH设备(MSTP)的主要特征。10G以太网技术的迅速发展,推动了以太网技术在城域网范围内的广泛应用,WAN接口(10Gbase-W)的引入为其向骨干网领域扩展提供了可能。
- 总之,以太网技术由于其简单、低成本、易扩展的优势,在用户桌面系统和企业内部网络已非常普及,随着技术的发展创新,其应用领域正逐步向接入网、城域网、甚至广域网/骨干网方面拓展,形成基于IP/Ethernet的端到端无缝连接。
3.2 Ethernet承载IP的例子
字段含义:
- Destination/目的字段:标识目标通信方的MAC地址 (6bytes)
- Source/源字段:标识发送端的MAC地址 (6bytes)
- Type/类型值:标志上层协议 (2bytes)
MAC地址:
- 所有设备的MAC地址是全球唯一的.
- MAC地址大小为6字节
- MAC地址的前半部分被称为"OUI代码"厂商唯一标识符, 后半部分厂商自动分配
4. 代码demo
#include <stdint.h>
/* mac 地址长度 */
#define MAC_ADDR_BTYES_LEN 6
/* ethernet头总长度 */
#define MAC_TOTAL_BTYES_LEN 14
/* 上层承载协议类型 */
#define PROTOCOL_UNKNOW 0
#define PROTOCOL_IPV4 1
#define PROTOCOL_IPV6 2
#define PROTOCOL_MPLS 3
#define PROTOCOL_VLAN 4
#define PROTOCOL_PPPOE 5
#define PROTOCOL_8021AD 6
typedef struct
{
uint8_t dest_addr[MAC_ADDR_BTYES_LEN];
uint8_t src_addr[MAC_ADDR_BTYES_LEN];
uint16_t next_protocol_type;
} st_ethernet_hdr;
static inline int get_eth_next_protocol(st_ethernet_hdr *dr)
{
switch (ntohs(dr->next_protocol_type)) {
case 0x0800:
return PROTOCOL_IPV4;
case 0x86dd:
return PROTOCOL_IPV6;
case 0x8847:
case 0x8848:
return PROTOCOL_MPLS;
case 0x8100:
case 0x9100:
return PROTOCOL_VLAN;
case 0x8864:
return PROTOCOL_PPPOE;
case 0x88a8:
return PROTOCOL_8021AD;
default:
return PROTOCOL_UNKNOW;
}
return PROTOCOL_UNKNOW;
}
/*
解码ethernet协议
@param1 pdata: 原始数据pdata的指针
@param2 len: 原始数据的长度
@return int:
PROTOCOL_UNKNOW : faild
other value : succeed
*/
int decode_ethernet(uint8_t *pdata, uint8_t len)
{
if (UNLIKELY(len < MAC_TOTAL_BTYES_LEN)) {
return PROTOCOL_UNKNOW;
}
st_ethernet_hdr *pethernet = (st_ethernet_hdr *)(pdata);
return get_eth_next_protocol(pethernet);
}
划重点: 为了解码Ethernet层,需要传入起始正确的数据和长度,在解码返回值不为PROTOCOL_UNKNOW时,说明解析成功,此时应该在调用函数之后,将指向数据的指针和长度分别偏移MAC_TOTAL_BTYES_LEN,即14bytes,来跳过Ethernet层。