您的位置:首页 > 运维架构

OPNET学习笔记之ethcoax_net-----mac

2012-09-11 16:16 676 查看


开始学习 eth_mac_v2

状态机如上图所示:

START出口代码 start状态为什么作用是确保地址正确呢??????

/* Obtain the address assigned to this node as it might */

/* have changed during auto-addressing. */

op_ima_obj_attr_get (mac_attr_objid, "Address", &my_32bit_address);

/* Store the address as 64-bit integer, since ARP was */

/* enhanced to support 48-bit MAC addresses. */

my_address = my_32bit_address;

/* Register station's MAC address into model-wide */

/* registery, since the address assignment is final now. */

oms_pr_attr_set (own_process_record_handle,

"address", OMSC_PR_INT64, my_address,

"protocol", OMSC_PR_STRING, "mac",

"mac_type", OMSC_PR_STRING, "eth_coax",

"auto address handle", OMSC_PR_POINTER, oms_aa_handle,

OPC_NIL);

/* Set the destination as an invalid destination if the MAC */

/* is part of a bridge/switch. */

if (mac_port_of_a_bridge_switch_node == OPC_TRUE)

oms_aa_dest_status_set (oms_aa_handle, (int) my_address, OmsC_Aa_Invalid_Destination);

TX_WAIT入口代码

/* In this state the MAC layer waits for a new */

/* frame to arrive from the higher layer. */

/* Physical layer events are not of interest and */

/* may be masked until frame processing begins. */

eth_mac_phys_layer_ignore (); 一直等待从高层发来的帧 忽略物理层的中断

FB中函数定义

static void

eth_mac_phys_layer_ignore () 忽略物理层的中断

{

/** Disable reception of physical layer events. **/

FIN (eth_mac_phys_layer_ignore ());

op_intrpt_disable (OPC_INTRPT_STAT, DEFERENCE_INSTAT, OPC_FALSE); op_intrpt_disable(type,code,next) next 是boolean型,OPC_TURE只失能以后来的中断//OPC_FALSE 无限制中断来的时间

op_intrpt_disable (OPC_INTRPT_STAT, COLLISION_DETECT_INSTAT, OPC_FALSE);

op_intrpt_disable (OPC_INTRPT_STAT, TRANSMITTING_INSTAT, OPC_FALSE);

FOUT;

}

当有帧到来时 TX_WAIT出口函数

/* Store interrupt related information into */
保存中断相关信息 以便以后调用

/* temporary variables for quick access. */

intrpt_type = op_intrpt_type ();

if (intrpt_type == OPC_INTRPT_STRM)

{

intrpt_strm = op_intrpt_strm ();

}

/* If the event was an arrival from the physical */

/* layer, accept and decapsulate the packet. */

if (intrpt_type == OPC_INTRPT_STRM &&

intrpt_strm == LOW_LAYER_INPUT_STREAM)

{

eth_mac_phys_pk_accept ();

}

/* Otherwise, if the event is an arrival from the */

/* higher layer, accept and enqueue the packet. */

else if (intrpt_type == OPC_INTRPT_STRM &&

((intrpt_strm == strm_from_ip) ||

(intrpt_strm == strm_from_ipx) ||

(intrpt_strm == HIGH_LAYER_INPUT_STREAM)))

{

eth_mac_llc_pk_accept ();

}

FRM_START 强制状态入口函数

/* Dequeue a new frame for transmission. */ 取出一个新的帧用于传输

current_frame = op_subq_pk_remove (0, OPC_QPOS_HEAD); // op_subq_pk_remove(subq_index, pos_index)获得指定序列指定位置中的包的指针,并把包从序列中删除

if (current_frame == OPC_NIL) {

eth_mac_error ("Unable to get outgoing frame from queue.",

"Queue is not empty: some error must have occurred.",

OPC_NIL);

}

/* Initialize transmission state variables. */ 初始化传输的状态变量

attempts = 0;

tx_comp_status = STATUS_OK;

frame_waiting = 1; 将帧等待的标志位置高

/* Notify the deference process that a frame is waiting. */

op_stat_write (frame_handle, 1.0); 将帧句柄也置高,来通知进程有帧在等待

分支1 当DEFERENCE_OFF 发生时 进入TX_START状态

#define DEFERENCE_OFF (op_stat_local_read (DEFERENCE_INSTAT) == 0.0)
当DEFERENCE_INSTAT标志变低时 mac层即可发送帧 什么事件触发标志变低呢

分支2 当deference flag 标志为高时 进入DEF_WAIT状态

DEF_WAIT入口函数

/* Enable physical layer events. */

eth_mac_phys_layer_listen (); 使能物理层中断

在此处等待,直到DEFERENCE_LOW发生 进入TX_START状态

#define DEFERENCE_LOW (op_intrpt_type () == OPC_INTRPT_STAT && \

op_intrpt_stat () == DEFERENCE_INSTAT && \

DEFERENCE_OFF)

TX_START 强制状态入口函数

/* Deference variable is low, so transmission can */

/* begin now. Create a copy of the current frame. */ mac开始发送帧了

tx_frame = op_pk_copy (current_frame); 复制当前帧

if (tx_frame == OPC_NIL)

{

eth_mac_error ("Unable to copy current outgoing frame.",

OPC_NIL, OPC_NIL);

}

/* Increment the number of attempts made */

/* so far on the current frame. */

attempts++; attempts代表什么???

/* The frame is no longer waiting. */ 帧不再等待,将帧等待标志位置低,并且置低句柄

/* Notify the deference process. */

frame_waiting = 0;

op_stat_write (frame_handle, frame_waiting);

/* Allow for debugger breaking at this point. */

op_prg_odb_bkpt ("tx_start"); 设置一个断点
以便ODB调试

if (op_prg_odb_pktrace_active (tx_frame)) 确定指定的包是否被ODB跟踪返回boolean型

{

sprintf (str, "packet id (" SIMC_PK_ID_FMT ")", op_pk_id (tx_frame));

op_prg_odb_print_major ("Sending New Frame", str, OPC_NIL);
输出Sending New Frame

}

/* Record the start time for the transmission attempt */记录开始传输的时间,以便判断是否发生延迟碰撞(即碰撞超过一个时间片)

/* in order to determine if late collisions (collisions */

/* beyond one slot time) occur. */

frame_start_time = op_sim_time ();

/* send frame to bus transmitter */ 将帧发到总线发射机

op_pk_send (tx_frame, LOW_LAYER_OUTPUT_STREAM);

TXEV_WAIT入口函数

/* Enable physical layer events. */ 使能物理层事件

eth_mac_phys_layer_listen ();

static void

eth_mac_phys_layer_listen ()

{

/** Disable reception of physical layer events. **/

FIN (eth_mac_phys_layer_listen ());

op_intrpt_enable (OPC_INTRPT_STAT, DEFERENCE_INSTAT);

op_intrpt_enable (OPC_INTRPT_STAT, COLLISION_DETECT_INSTAT);

op_intrpt_enable (OPC_INTRPT_STAT, TRANSMITTING_INSTAT);

FOUT;

}

分支1 当XMITTING_LOW 发生时 :当传送标志为低时

#define XMITTING_LOW (op_intrpt_type () == OPC_INTRPT_STAT && \

op_intrpt_stat () == TRANSMITTING_INSTAT && \

op_stat_local_read (TRANSMITTING_INSTAT) == 0.0)

执行出口函数:

/* Store interrupt related information into */

/* temporary variables for quick access. */

intrpt_type = op_intrpt_type ();

if (intrpt_type == OPC_INTRPT_STRM)

{

intrpt_strm = op_intrpt_strm ();

}

/* If the event was an arrival from the physical */

/* layer, accept and decapsulate the packet. */

if (intrpt_type == OPC_INTRPT_STRM &&

intrpt_strm == LOW_LAYER_INPUT_STREAM)

{

eth_mac_phys_pk_accept ();

}

/* Otherwise, if the event is an arrival from the */

/* higher layer, accept and enqueue the packet. */

else if (intrpt_type == OPC_INTRPT_STRM &&

((intrpt_strm == strm_from_ip) ||

(intrpt_strm == strm_from_ipx) ||

(intrpt_strm == HIGH_LAYER_INPUT_STREAM)))

{

eth_mac_llc_pk_accept ();

}
到此之前的函数与TX_WAIT出口函数相同
功能也相同

if (XMITTING_LOW) 如果执行XMITTING_LOW这条路径,就把attempts的值写到retrans_handle中

{

op_stat_write (retrans_handle, attempts);

}

FRM_END强制状态入口函数

/* Enable all interrupts */

op_intrpt_enable_all (); 使能所有中断

/* Deallocate the frame stored for retransmission purposes. */ 释放用于重传的帧

op_pk_destroy (current_frame);

/* Record extra data-points to enable proper computation of */ 使用额外的数据点来记录sum/time 的性能

/* the "sum/time" based statistics. */

op_stat_write(bit_sec_load_handle, 0.0);

op_stat_write(packet_sec_load_handle, 0.0);

分支1 .1 当QUEUE_EMPTY 时 又回到TX_WAIT状态

#define QUEUE_EMPTY (op_q_stat (OPC_QSTAT_PKSIZE) == 0.0)

分支1.2 如果队列不为空 跳到FRM_START状态

分支2 当COLL_DET_HIGH 发生时 执行TXEV_WAIT状态的出口函数 和SET_ENTRY 进入collision状态

#define COLL_DET_HIGH (op_intrpt_type () == OPC_INTRPT_STAT && \

op_intrpt_stat () == COLLISION_DETECT_INSTAT &&\

op_stat_local_read (COLLISION_DETECT_INSTAT) == 1.0)

TXEV_WAIT出口函数 保存中断相关信息
以便以后调用

SET_ENTRY

#define SET_ENTRY reentry = 0;

collision状态入口函数

if (!reentry) default情况下将reentry置高 还如何进入程序????

{

/* A collision has occured. Continue transmitting for */

/* JAM_SIZE bit-times, at which time the transmission */

/* will be aborted. */

op_stat_write (collision_num_handle, 1.0); 将碰撞标志位置高

evh = op_intrpt_schedule_self (op_sim_time () + JAM_SIZE / bit_rate, 0); 获取碰撞时间

if (op_ev_valid (evh) == OPC_FALSE)

{

eth_mac_error ("Unable to schedule end of post-collision jamming.",

OPC_NIL, OPC_NIL);

}

/* During the jam period, ignore physical layer events. */

eth_mac_phys_layer_ignore (); 碰撞期间忽略物理层的事件

/* Compute time from leading edge of frame to */

/* the time at which the collision occurred. */ 计算从帧开始传输到现在碰撞所用时间 写入frag_time中

frag_time = op_sim_time () - frame_start_time;

}

default中为什么把reentry中置高了????

当JAM_END时,

#define JAM_END (op_intrpt_type () == OPC_INTRPT_SELF) 有自中断产生 // #define JAM_END (op_intrpt_type () == OPC_INTRPT_SELF)

//#define BACKOFF_END (op_intrpt_type () == OPC_INTRPT_SELF)?????为什么条件一样

执行collision出口函数 此处同TX_WAIT TXEV_WAIT的出口函数,保存中断信息

/* Store interrupt re lated information into */

/* temporary variables for quick access. */

intrpt_type = op_intrpt_type ();

if (intrpt_type == OPC_INTRPT_STRM)

{

intrpt_strm = op_intrpt_strm ();

}

/* If the event was an arrival from the physical */

/* layer, accept and decapsulate the packet. */

if (intrpt_type == OPC_INTRPT_STRM &&

intrpt_strm == LOW_LAYER_INPUT_STREAM)

{

eth_mac_phys_pk_accept ();

}

/* Otherwise, if the event is an arrival from the */

/* higher layer, accept and enqueue the packet. */

else if (intrpt_type == OPC_INTRPT_STRM &&

((intrpt_strm == strm_from_ip) ||

(intrpt_strm == strm_from_ipx) ||

(intrpt_strm == HIGH_LAYER_INPUT_STREAM)))

{

eth_mac_llc_pk_accept ();

}

进入强制状态ABORT 入口函数

/* Jamming bit sequence has been transmitted. */

/* Stop the remainder of the packet from being */

/* transmitted. */

if (op_ima_obj_command (tx_channel_objid, "abort") == OPC_COMPCODE_FAILURE)

/******op_ima_obj_command (objid,
cmd_name) 在指定的对象中执行cmd_name 命令 “abort” 对于 point-to-point link bus link radio transmitter channel 方式:immediately aborts the current packet transmission "flush"对于radio receiver
channel :immediately removes all packets in the process of being received *******/

{

eth_mac_warn ("Unable to issue ABORT command to transmitter channel.",

OPC_NIL, OPC_NIL);

}
/* If the length of the fragment is greater */ 判断是否为延迟碰撞

/* than a slot time, this is a late collision. */

if (frag_time > SLOT_TIME)

tx_comp_status = STATUS_ERR_LATE_COLL;

else if (attempts >= ATTEMPT_LIMIT)

tx_comp_status = STATUS_ERR_EXCESS_COLL;

else

tx_comp_status = STATUS_RETRANSMIT_PENDING;

分支2.1

如果此时 EXCESS_COL 或者LATE_COL发生,则进入FRM_END状态

#define EXCESS_COL (tx_comp_status == STATUS_ERR_EXCESS_COLL)

#define LATE_COL (tx_comp_status == STATUS_ERR_LATE_COLL)

分支2.2

其他情况,执行SET_ENTRY

#define SET_ENTRY reentry = 0;

进入BACK_OFF状态 入口代码

if (!reentry)

{

/* Compute backoff interval using truncated */ 使用截断的二进制指数进程 计算补偿间隔

/* binary exponential process. */

/* Unit for retransmission scheduling is the slot time and */ 重传调度的单位是时间片

/* the upper bound is based on number of transmissions to */上层绑定是基于当前帧的传输数目

/* to date of the current frame. */

/* If this is the first attempt, there */ 如果是第一次尝试,则有两种可能的补偿时间片

/* are two possible backoff slots. */

if (attempts == 1)

max_backoff = 2;

/* Otherwise the number of possible slots grows */否则时间片数目会按照指数增长直到一定界限

/* exponentially until it exceeds a fixed limit. */

else if (attempts <= BACKOFF_LIMIT)

max_backoff = max_backoff * 2;

/* Obtain a uniformly distributed random integer */ 在0-界限中获取唯一的指数分布

/* between 0 and the backoff limit. */

backoff_slots = op_dist_uniform (max_backoff);

if (backoff_slots == OPC_DBL_INVALID)

{

eth_mac_error ("Unable to choose a number of backoff slots.", OPC_NIL, OPC_NIL);

}

/* Set a timer for the end of the backoff interval. */

evh = op_intrpt_schedule_self (op_sim_time () + (int) backoff_slots * SLOT_TIME, 0); 此处不理解???

if (op_ev_valid (evh) == OPC_FALSE)

{

eth_mac_error ("Unable to schedule end to backoff interval.", OPC_NIL, OPC_NIL);

}

}

分支2.2.1 当BACKOFF_END&&DEFERENCE_OFF 执行出口代码,进入TX_START状态

#define BACKOFF_END (op_intrpt_type () == OPC_INTRPT_SELF)

#define DEFERENCE_OFF (op_stat_local_read (DEFERENCE_INSTAT) == 0.0)

分支2.2.2 当BACKOFF_END && DEFERENCE_ON 执行出口函数 并执行SET_FRM_WAIT 进入DEF_WAIT状态

#define BACKOFF_END (op_intrpt_type () == OPC_INTRPT_SELF)

#define DEFERENCE_ON (op_stat_local_read (DEFERENCE_INSTAT) == 1.0)

#define SET_FRM_WAIT {frame_waiting = 1;

op_stat_write (frame_handle, 1.0);}

BACKOFF出口代码 保存中断信息以便调用 同TX_WAIT和 DEF_WAIT的出口函数

/* Store interrupt related information into */

/* temporary variables for quick access. */

intrpt_type = op_intrpt_type ();

if (intrpt_type == OPC_INTRPT_STRM)

{

intrpt_strm = op_intrpt_strm ();

}

/* If the event was an arrival from the physical */

/* layer, accept and decapsulate the packet. */

if (intrpt_type == OPC_INTRPT_STRM &&

intrpt_strm == LOW_LAYER_INPUT_STREAM)

{

eth_mac_phys_pk_accept ();

}

/* Otherwise, if the event is an arrival from the */

/* higher layer, accept and enqueue the packet. */

else if (intrpt_type == OPC_INTRPT_STRM &&

((intrpt_strm == strm_from_ip) ||

(intrpt_strm == strm_from_ipx) ||

(intrpt_strm == HIGH_LAYER_INPUT_STREAM)))

{

eth_mac_llc_pk_accept ();

}

状态转换图如下所示
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: