从hdr_ip::access()谈对ns2数据包的理解

本文解析了NS2中hdr_ip::access()函数的作用,详细介绍了该函数如何通过偏移量获取Packet中的IP头部信息,并扩展解释了类似宏定义的使用方式。

在NS2的代码中,我们经常看到hdr_ip::access(p)这样类似的语句,如何理解呢?理解这一点后,有助于我们对通信中包结构的理解,本篇文章以hdr_ip::access()为例说明。

一、在ip.h文件可看到hdr_ip的定义

struct hdr_ip {
	/* common to IPv{4,6} */
	ns_addr_t	src_;
	ns_addr_t	dst_;
	int		ttl_;

	/* Monarch extn */
// 	u_int16_t	sport_;
// 	u_int16_t	dport_;
	
	/* IPv6 */
	int		fid_;	/* flow id */
	int		prio_;

	static int offset_;
	inline static int& offset() { return offset_; }
	inline static hdr_ip* access(const Packet* p) {
		return (hdr_ip*) p->access(offset_);
	}

	/* per-field member acces functions */
	ns_addr_t& src() { return (src_); }
	nsaddr_t& saddr() { return (src_.addr_); }
        int32_t& sport() { return src_.port_;}

	ns_addr_t& dst() { return (dst_); }
	nsaddr_t& daddr() { return (dst_.addr_); }
        int32_t& dport() { return dst_.port_;}
	int& ttl() { return (ttl_); }
	/* ipv6 fields */
	int& flowid() { return (fid_); }
	int& prio() { return (prio_); }
};

二、实际是调用Packet.h的access(offset_)

inline unsigned char* access(int off) const {
		if (off < 0)
			abort();
		return (&bits_[off]);
	}

而bits_是packet.h的成员变量,代表包头数据,实际上是一个无符号字符串的起始指针。

private:
	unsigned char* bits_;	// header bits

hdr_ip::access()返回是packet.h中的偏移offset_字节的指针,只不过强制转换成了hdr_ip*类型,同时偏移量offset_在结构体hdr_ip中定义。

三、扩展

理解了以上内容,我们就很好理解以下这些代码了。

#define HDR_CMN(p)      (hdr_cmn::access(p))
#define HDR_ARP(p)      (hdr_arp::access(p))
#define HDR_MAC(p)      (hdr_mac::access(p))
#define HDR_MAC802_11(p) ((hdr_mac802_11 *)hdr_mac::access(p))
#define HDR_MAC_TDMA(p) ((hdr_mac_tdma *)hdr_mac::access(p))
#define HDR_SMAC(p)     ((hdr_smac *)hdr_mac::access(p))
#define HDR_LL(p)       (hdr_ll::access(p))
#define HDR_HDLC(p)     ((hdr_hdlc *)hdr_ll::access(p))
#define HDR_IP(p)       (hdr_ip::access(p))
#define HDR_RTP(p)      (hdr_rtp::access(p))
#define HDR_TCP(p)      (hdr_tcp::access(p))
#define HDR_SCTP(p)     (hdr_sctp::access(p))
#define HDR_SR(p)       (hdr_sr::access(p))
#define HDR_TFRC(p)     (hdr_tfrc::access(p))
#define HDR_TORA(p)     (hdr_tora::access(p))
#define HDR_IMEP(p)     (hdr_imep::access(p))
#define HDR_CDIFF(p)    (hdr_cdiff::access(p))  /* chalermak's diffusion*/
//#define HDR_DIFF(p)     (hdr_diff::access(p))  /* SCADD's diffusion ported into ns */
#define HDR_LMS(p)		(hdr_lms::access(p))

同时,我们也知道,在定义一个新的数据包时候,哪些内容是固定的写法了,就解决了对NS2数据包代码的理解。

原创文章,转载请注明!

/* uc tpdata key */ #define UC_SFLOW_ENABLE "UC_SFLOW_ENABLE" #define UC_SFLOW_AGENT_IP "UC_SFLOW_AGENT_IP" #define UC_SFLOW_COL_IP_IDX "UC_SFLOW_COL_IP:%d" #define UC_SFLOW_COL_DESC_IDX "UC_SFLOW_COL_DESC:%d" #define UC_SFLOW_COL_MAX_DATA_IDX "UC_SFLOW_COL_MAX_DATA:%d" #define UC_SFLOW_COL_PORT_IDX "UC_SFLOW_COL_PORT:%d" #define UC_SFLOW_COL_TIMEOUT_IDX "UC_SFLOW_COL_TIMEOUT:%d" #define UC_SFLOW_SAM_EGRATE "UC_SFLOW_SAM_EGRATE" #define UC_SFLOW_SAM_IGRATE "UC_SFLOW_SAM_IGRATE" #define UC_SFLOW_SAM_PORT_COL_ID_IDX "UC_SFLOW_SAM_PORT_COL_ID:%d" #define UC_SFLOW_SAM_PORT_MAXHDR_IDX "UC_SFLOW_SAM_PORT_MAXHDR:%d" /* rtd tpdata key */ #define RTD_SFLOW_PORT_SEQ_IDX "RTD_SFLOW_PORT_SEQ:%d" #define RTD_SFLOW_COL_SEQ_IDX "RTD_SFLOW_COL_SEQ:%d" #define RTD_SFLOW_COL_START_TIME_IDX "RTD_SFLOW_COL_START_TIME:%d" #define RTD_SFLOW_FLOW_SAM_NUM "RTD_SFLOW_FLOW_SAM_NUM" #define RTD_SFLOW_FLOW_SAM_IDX "RTD_SFLOW_FLOW_SAM:%d" #define RTD_SFLOW_FLOW_SAM_ENTERP "enterp" #define RTD_SFLOW_FLOW_SAM_LEN "len" #define RTD_SFLOW_FLOW_SAM_SEQ_NUM "seqNum" #define RTD_SFLOW_FLOW_SAM_SRCID "srcId" #define RTD_SFLOW_FLOW_SAM_SAMRATE "samRate" #define RTD_SFLOW_FLOW_SAM_SAMPOOL "samPool" #define RTD_SFLOW_FLOW_SAM_DROPS "drops" #define RTD_SFLOW_FLOW_SAM_INPUT "input" #define RTD_SFLOW_FLOW_SAM_OUTPUT "output" #define RTD_SFLOW_FLOW_SAM_RECORDS "records" #define RTD_SFLOW_SAM_HDR_IDX "RTD_SFLOW_SAM_HDR_IDX:%d" #define RTD_SFLOW_SAM_HDR_ENTERP "enterp" #define RTD_SFLOW_SAM_HDR_DATA_LEN "flowDataLen" #define RTD_SFLOW_SAM_HDR_PROTOCOL "hdrProtocol" #define RTD_SFLOW_SAM_HDR_FRAME_LEN "frameLen" #define RTD_SFLOW_SAM_HDR_STRIPPED "stripped" #define RTD_SFLOW_SAM_HDR_FOLLOW_LEN "followLen" #define RTD_SFLOW_CP_HDR_IDX "RTD_SFLOW_CP_HDR_IDX:%d" #define RTD_SFLOW_CP_HDR_PKT "pkt" #define RTD_SFLOW_CP_HDR_COL_ID "colId" #define RTD_SFLOW_CP_HDR_LEN "len" #define RTD_SFLOW_DATAGRAM_HDR_IDX "RTD_SFLOW_DATAGRAM_HDR_IDX:%d" #define RTD_SFLOW_DATAGRAM_HDR_VERSION "version" #define RTD_SFLOW_DATAGRAM_HDR_AGENT_ADDR_VER "agentAddrVer" #define RTD_SFLOW_DATAGRAM_HDR_AGENT_ADDR "agentAddr" #define RTD_SFLOW_DATAGRAM_HDR_SUB_AGENT_ID "subAgentId" #define RTD_SFLOW_DATAGRAM_HDR_SEQ_NUM "seqNum" #define RTD_SFLOW_DATAGRAM_HDR_UPTIME "uptime" #define RTD_SFLOW_DATAGRAM_HDR_NUMSAMS "numSams" 解释下各个字段含义
最新发布
09-24
<think> 我们有一系列的宏定义,用于配置和存储sFlow相关的参数。这些宏分为两类:UC(可能是用户配置)和RTD(可能是运行时数据)。下面将逐一解释这些宏的含义和作用。 ### 一、UC (User Configuration) 配置宏 这些宏定义了sFlow配置参数的键名,用于从配置存储(如数据库或配置文件)中读取或写入配置值。 1. **全局开关与Agent IP** ```c #define UC_SFLOW_ENABLE "UC_SFLOW_ENABLE" // sFlow功能全局使能开关(1=启用,0=禁用) #define UC_SFLOW_AGENT_IP "UC_SFLOW_AGENT_IP" // sFlow Agent的IP地址 ``` 2. **Collector配置(索引形式)** ```c // 使用索引%d区分多个Collector(如0,1,2...) #define UC_SFLOW_COL_IP_IDX "UC_SFLOW_COL_IP:%d" // Collector的IP地址 #define UC_SFLOW_COL_DESC_IDX "UC_SFLOW_COL_DESC:%d" // Collector的描述信息 #define UC_SFLOW_COL_MAX_DATA_IDX "UC_SFLOW_COL_MAX_DATA:%d"// 单个sFlow报文的最大数据量(字节) #define UC_SFLOW_COL_PORT_IDX "UC_SFLOW_COL_PORT:%d" // Collector的UDP端口(默认6343) #define UC_SFLOW_COL_TIMEOUT_IDX "UC_SFLOW_COL_TIMEOUT:%d" // 采样数据等待超时时间(毫秒) ``` 3. **采样率配置** ```c #define UC_SFLOW_SAM_EGRATE "UC_SFLOW_SAM_EGRATE" // 出方向(egress)采样率(1/N) #define UC_SFLOW_SAM_IGRATE "UC_SFLOW_SAM_IGRATE" // 入方向(ingress)采样率(1/N) ``` 4. **端口级采样配置(索引形式)** ```c // 端口索引%d对应物理端口号(如1,2,24...) #define UC_SFLOW_SAM_PORT_COL_ID_IDX "UC_SFLOW_SAM_PORT_COL_ID:%d" // 绑定到该端口的Collector ID #define UC_SFLOW_SAM_PORT_MAXHDR_IDX "UC_SFLOW_SAM_PORT_MAXHDR:%d" // 该端口的最大采样包头长度 ``` ### 二、RTD (RunTime Data) 运行时数据宏 这些宏定义了运行时数据的存储键名,用于记录sFlow运行过程中的实时状态和采样数据。 1. **端口序列号** ```c #define RTD_SFLOW_PORT_SEQ_IDX "RTD_SFLOW_PORT_SEQ:%d" // 端口的采样序列号(按端口索引) ``` 2. **Collector序列号** ```c #define RTD_SFLOW_COL_SEQ_IDX "RTD_SFLOW_COL_SEQ:%d" // Collector的数据报序列号(按Collector索引) ``` 3. **Collector启动时间** ```c #define RTD_SFLOW_COL_START_TIME_IDX "RTD_SFLOW_COL_START_TIME:%d" // Collector的启动时间戳(秒) ``` 4. **流采样记录存储** ```c // 流采样记录集合管理 #define RTD_SFLOW_FLOW_SAM_NUM "RTD_SFLOW_FLOW_SAM_NUM" // 当前存储的流采样记录数量 #define RTD_SFLOW_FLOW_SAM_IDX "RTD_SFLOW_FLOW_SAM:%d" // 单个流采样记录(索引%d) // 流采样记录字段(嵌套在RTD_SFLOW_FLOW_SAM_IDX下) #define RTD_SFLOW_FLOW_SAM_ENTERP "enterp" // 企业格式标识(固定0x00000001) #define RTD_SFLOW_FLOW_SAM_LEN "len" // 记录长度 #define RTD_SFLOW_FLOW_SAM_SEQ_NUM "seqNum" // 流采样序列号 #define RTD_SFLOW_FLOW_SAM_SRCID "srcId" // 采样源ID #define RTD_SFLOW_FLOW_SAM_SAMRATE "samRate" // 采样率 #define RTD_SFLOW_FLOW_SAM_SAMPOOL "samPool" // 采样池大小(可采样包总数) #define RTD_SFLOW_FLOW_SAM_DROPS "drops" // 丢弃样本数 #define RTD_SFLOW_FLOW_SAM_INPUT "input" // 输入接口索引 #define RTD_SFLOW_FLOW_SAM_OUTPUT "output" // 输出接口索引(含广播标志) #define RTD_SFLOW_FLOW_SAM_RECORDS "records" // 包含的子记录数 ``` 5. **采样包头元数据存储** ```c // 包头元数据记录(索引%d) #define RTD_SFLOW_SAM_HDR_IDX "RTD_SFLOW_SAM_HDR_IDX:%d" // 字段定义 #define RTD_SFLOW_SAM_HDR_ENTERP "enterp" // 企业格式标识 #define RTD_SFLOW_SAM_HDR_DATA_LEN "flowDataLen" // 流数据长度 #define RTD_SFLOW_SAM_HDR_PROTOCOL "hdrProtocol" // 包头协议类型 #define RTD_SFLOW_SAM_HDR_FRAME_LEN "frameLen" // 原始帧长度 #define RTD_SFLOW_SAM_HDR_STRIPPED "stripped" // 被剥离的字节数 #define RTD_SFLOW_SAM_HDR_FOLLOW_LEN "followLen" // 跟随的实际包头长度 ``` 6. **采样包头内容存储** ```c // 包头内容记录(索引%d) #define RTD_SFLOW_CP_HDR_IDX "RTD_SFLOW_CP_HDR_IDX:%d" // 字段定义 #define RTD_SFLOW_CP_HDR_PKT "pkt" // 存储的包头二进制数据 #define RTD_SFLOW_CP_HDR_COL_ID "colId" // 目标Collector ID #define RTD_SFLOW_CP_HDR_LEN "len" // 包头实际长度 ``` 7. **数据报头部存储** ```c // 数据报头部记录(索引%d) #define RTD_SFLOW_DATAGRAM_HDR_IDX "RTD_SFLOW_DATAGRAM_HDR_IDX:%d" // 字段定义 #define RTD_SFLOW_DATAGRAM_HDR_VERSION "version" // sFlow版本(如5) #define RTD_SFLOW_DATAGRAM_HDR_AGENT_ADDR_VER "agentAddrVer" // Agent IP地址版本(0=IPv4) #define RTD_SFLOW_DATAGRAM_HDR_AGENT_ADDR "agentAddr" // Agent的IPv4地址 #define RTD_SFLOW_DATAGRAM_HDR_SUB_AGENT_ID "subAgentId" // 子代理ID #define RTD_SFLOW_DATAGRAM_HDR_SEQ_NUM "seqNum" // 数据报序列号(全局递增) #define RTD_SFLOW_DATAGRAM_HDR_UPTIME "uptime" // Agent运行时间(毫秒) #define RTD_SFLOW_DATAGRAM_HDR_NUMSAMS "numSams" // 数据报中的样本数 ``` ### 三、配置与运行时数据协作示例 1. **初始化阶段**: - 读取`UC_SFLOW_ENABLE`判断是否启用sFlow - 加载Agent IP(`UC_SFLOW_AGENT_IP`) - 遍历索引加载Collector配置(IP/端口等) 2. **采样阶段**: - 根据端口索引从`UC_SFLOW_SAM_PORT_COL_ID_IDX`获取Collector ID - 更新端口序列号(`RTD_SFLOW_PORT_SEQ_IDX`) 3. **数据封装阶段**: - 生成流采样记录(`RTD_SFLOW_FLOW_SAM_IDX`) - 填充包头元数据(`RTD_SFLOW_SAM_HDR_IDX`)和内容(`RTD_SFLOW_CP_HDR_IDX`) - 构建数据报头部(`RTD_SFLOW_DATAGRAM_HDR_IDX`) 4. **发送阶段**: - 按Collector索引获取序列号(`RTD_SFLOW_COL_SEQ_IDX`)并递增 - 发送后删除或标记过期数据 §§相关问题§§ 1. `UC_SFLOW_SAM_PORT_COL_ID_IDX` 中的端口索引如何与物理端口映射? 2. `RTD_SFLOW_PORT_SEQ_IDX` 序列号在采样过程中如何更新? 3. 运行时数据(如流采样记录)的存储介质是什么(内存/数据库)? 4. 多个Collector配置时,如何避免`RTD_SFLOW_COL_SEQ_IDX`的序列号冲突? 5. `RTD_SFLOW_FLOW_SAM_NUM` 记录的流采样数量达到上限后如何处理新采样? </think> 以下是对提供的sFlow配置宏定义及运行时数据结构键名的详细解释,按功能分类说明: --- ### **一、配置参数键(UC前缀:User Config)** #### 1. **全局配置** ```c #define UC_SFLOW_ENABLE "UC_SFLOW_ENABLE" // sFlow功能总开关(1=启用,0=禁用) #define UC_SFLOW_AGENT_IP "UC_SFLOW_AGENT_IP" // sFlow Agent的IPv4地址 ``` #### 2. **Collector配置** ```c #define UC_SFLOW_COL_IP_IDX "UC_SFLOW_COL_IP:%d" // 索引%d对应Collector的IP地址 #define UC_SFLOW_COL_DESC_IDX "UC_SFLOW_COL_DESC:%d" // Collector描述信息 #define UC_SFLOW_COL_MAX_DATA_IDX "UC_SFLOW_COL_MAX_DATA:%d" // 单个sFlow报文最大长度 #define UC_SFLOW_COL_PORT_IDX "UC_SFLOW_COL_PORT:%d" // Collector监听端口 #define UC_SFLOW_COL_TIMEOUT_IDX "UC_SFLOW_COL_TIMEOUT:%d" // 采样数据缓存超时时间 ``` **说明**:`%d`为Collector索引ID(如0,1,2...),支持多Collector配置 #### 3. **采样率配置** ```c #define UC_SFLOW_SAM_EGRATE "UC_SFLOW_SAM_EGRATE" // 出方向(egress)采样率(1/N) #define UC_SFLOW_SAM_IGRATE "UC_SFLOW_SAM_IGRATE" // 入方向(ingress)采样率(1/N) ``` #### 4. **端口级采样配置** ```c #define UC_SFLOW_SAM_PORT_COL_ID_IDX "UC_SFLOW_SAM_PORT_COL_ID:%d" // 端口绑定Collector ID #define UC_SFLOW_SAM_PORT_MAXHDR_IDX "UC_SFLOW_SAM_PORT_MAXHDR:%d" // 端口最大采样包头长度 ``` **说明**:`%d`为物理端口号(如1,2,24...) --- ### **二、运行时数据键(RTD前缀:RunTime Data)** #### 1. **序列号管理** ```c #define RTD_SFLOW_PORT_SEQ_IDX "RTD_SFLOW_PORT_SEQ:%d" // 端口的采样序列号 #define RTD_SFLOW_COL_SEQ_IDX "RTD_SFLOW_COL_SEQ:%d" // Collector的数据报序列号 ``` #### 2. **Collector状态** ```c #define RTD_SFLOW_COL_START_TIME_IDX "RTD_SFLOW_COL_START_TIME:%d" // Collector启动时间戳 ``` #### 3. **流采样记录(SFLFlow_sample字段)** ```c #define RTD_SFLOW_FLOW_SAM_NUM "RTD_SFLOW_FLOW_SAM_NUM" // 当前流采样记录总数 #define RTD_SFLOW_FLOW_SAM_IDX "RTD_SFLOW_FLOW_SAM:%d" // 索引%d的流采样记录 // 字段键(嵌套在RTD_SFLOW_FLOW_SAM_IDX下) #define RTD_SFLOW_FLOW_SAM_ENTERP "enterp" // 企业格式标识 #define RTD_SFLOW_FLOW_SAM_LEN "len" // 记录长度 #define RTD_SFLOW_FLOW_SAM_SEQ_NUM "seqNum" // 采样序列号 #define RTD_SFLOW_FLOW_SAM_SRCID "srcId" // 采样源ID(端口) #define RTD_SFLOW_FLOW_SAM_SAMRATE "samRate" // 采样率 #define RTD_SFLOW_FLOW_SAM_SAMPOOL "samPool" // 可采样数据包总量 #define RTD_SFLOW_FLOW_SAM_DROPS "drops" // 丢弃样本数 #define RTD_SFLOW_FLOW_SAM_INPUT "input" // 输入接口索引 #define RTD_SFLOW_FLOW_SAM_OUTPUT "output" // 输出接口索引(含广播标志) #define RTD_SFLOW_FLOW_SAM_RECORDS "records" // 包含的子记录数 ``` #### 4. **包头元数据(SFLSampled_header字段)** ```c #define RTD_SFLOW_SAM_HDR_IDX "RTD_SFLOW_SAM_HDR_IDX:%d" // 包头元数据记录索引 // 字段键 #define RTD_SFLOW_SAM_HDR_ENTERP "enterp" // 企业格式标识 #define RTD_SFLOW_SAM_HDR_DATA_LEN "flowDataLen" // 流数据长度 #define RTD_SFLOW_SAM_HDR_PROTOCOL "hdrProtocol" // 包头协议类型 #define RTD_SFLOW_SAM_HDR_FRAME_LEN "frameLen" // 原始帧长度 #define RTD_SFLOW_SAM_HDR_STRIPPED "stripped" // 被剥离字节数 #define RTD_SFLOW_SAM_HDR_FOLLOW_LEN "followLen" // 跟随包头长度 ``` #### 5. **采样包头内容(SF_copyHeader字段)** ```c #define RTD_SFLOW_CP_HDR_IDX "RTD_SFLOW_CP_HDR_IDX:%d" // 包头内容记录索引 // 字段键 #define RTD_SFLOW_CP_HDR_PKT "pkt" // 存储的包头二进制数据 #define RTD_SFLOW_CP_HDR_COL_ID "colId" // 目标Collector ID #define RTD_SFLOW_CP_HDR_LEN "len" // 实际包头长度 ``` #### 6. **数据报头部(SFLSample_datagram_hdr字段)** ```c #define RTD_SFLOW_DATAGRAM_HDR_IDX "RTD_SFLOW_DATAGRAM_HDR_IDX:%d" // 数据报头部索引 // 字段键 #define RTD_SFLOW_DATAGRAM_HDR_VERSION "version" // sFlow协议版本 #define RTD_SFLOW_DATAGRAM_HDR_AGENT_ADDR_VER "agentAddrVer" // Agent IP版本(0=IPv4) #define RTD_SFLOW_DATAGRAM_HDR_AGENT_ADDR "agentAddr" // Agent的IPv4地址 #define RTD_SFLOW_DATAGRAM_HDR_SUB_AGENT_ID "subAgentId" // 子代理标识 #define RTD_SFLOW_DATAGRAM_HDR_SEQ_NUM "seqNum" // 数据报序列号 #define RTD_SFLOW_DATAGRAM_HDR_UPTIME "uptime" // Agent运行时间(毫秒) #define RTD_SFLOW_DATAGRAM_HDR_NUMSAMS "numSams" // 包含的样本数 ``` --- ### **三、键名设计特点** 1. **分层结构** - 使用`%d`占位符实现动态索引(如端口/Collector/记录ID) - 嵌套字段通过二级键访问(如`RTD_SFLOW_FLOW_SAM_IDX`下的`seqNum`) 2. **数据分类** - **UC键**:持久化配置,重启后保留 - **RTD键**:运行时状态,设备重启后重置 3. **存储映射** 键名设计适配键值数据库(如Redis)或内存表,例如: - `SET RTD_SFLOW_PORT_SEQ:24 100`(设置端口24的序列号) - `HSET RTD_SFLOW_FLOW_SAM:5 seqNum 120`(设置记录5的序列号)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值