现在的位置: 首页 > 综合 > 正文

excoax_net学习笔记之eth_mac_v2 —–INIT 出口代码

2018年02月20日 ⁄ 综合 ⁄ 共 10646字 ⁄ 字号 评论关闭

 初学opnet  如理解有误,欢迎指正

INIT 出口代码   出口代码有点长,不要被吓到了奋斗

/* Obtain the address assigned to this node.   */
if (op_ima_obj_attr_get (mac_attr_objid, "Address", &my_32bit_address) //op_ima_obj_attr_get(objid,attr_name,value_ptr)  从指定的对象objid中获取属性attr_name放到value_ptr中    value_ptr是void*型   返回值为compcode

 == OPC_COMPCODE_FAILURE)
 {
 eth_mac_error ("Unable to read station address attribute.", OPC_NIL, OPC_NIL);
 }

/* Perform auto-addressing for the MAC address dynamically addresses·, if auto-assigned, the address resolution function also detects duplicate */
/* static assignments. By default each address is  */
/* considered as being a valid destination unless it is */
/* explicitly set.     */
oms_aa_address_resolve (oms_aa_handle, mac_attr_objid, &my_32bit_address);//

Creates a new, unique  address (if theaddress is auto-assigned), or verifies that theaddress
is unique (if the address is explicitly assigned). 所以有检测重复分配的功能

 

/* Initialize and export the frame-waiting variable used */  初始化并导出帧等待变量
/* by deference process in computing deference intervals. */
frame_waiting = 0.0;
op_stat_write (frame_handle, frame_waiting);

/* Obtain the node's object id. */
own_node_objid = op_topo_parent (my_objid); 获得节点id

/* Obtain the process's process handle. */
own_prohandle = op_pro_self ();  //获得进程句柄

/* Obtain the name of the process. */
op_ima_obj_attr_get (my_objid, "process model", proc_model_name);

/* Register this Ethernet MAC process in the model-wide registry. */  

own_process_record_handle = (OmsT_Pr_Handle) oms_pr_process_register (own_node_objid, my_objid,  获得记录进程注册信息的句柄
 own_prohandle, proc_model_name);

/* Register the protocol attribute and mac type info of this  */

/* process into the model-wide registry.        */
oms_pr_attr_set (own_process_record_handle, "protocol", OMSC_PR_STRING, "mac", OPC_NIL); 在句柄中注册协议信息  name type value ...OPNIL
oms_pr_attr_set (own_process_record_handle, "mac_type", OMSC_PR_STRING, "eth", OPC_NIL); /*两句可以合并为一句   oms_pr_attr_set    (own_process_record_handle, "protocol", OMSC_PR_STRING, "mac", "mac_type", OMSC_PR_STRING, "eth",OPC_NIL);*/

/* Determine object identifier of transmitter connecting */
/* the MAC layer to the bus.  This Objid is needed to abort */
/* collided transmissions in the "COLLISION" state.   */
tx_objid = op_topo_assoc (op_id_self (), OPC_TOPO_ASSOC_OUT,
 OPC_OBJTYPE_BUTX, LOW_LAYER_OUTPUT_STREAM);   //获得与进程id的出线相连的id    即发射机的id
if (tx_objid == OPC_OBJID_INVALID)
 {
 eth_mac_error ("Unable to get Objid of transmitter module.",
  "Node model is probably incorrect; make sure that",
  "eth_mac connects to a bus transmitter through output stream 0.");
 } 

/* Get the compound attribute tx id */获得发射机id的综合属性
op_ima_obj_attr_get (tx_objid, "channel", &tx_comp_attr_objid); 此处将发射机id的channel属性填入tx_comp_attr_objid
if (tx_comp_attr_objid == OPC_OBJID_INVALID)
 {
 eth_mac_error("Unable to get Objid of transmitter compound attribute",OPC_NIL,OPC_NIL);
 }

/* determine the bitrate used by the transmitter's channel */确定发射机信道的比特率
tx_channel_objid = op_topo_child(tx_comp_attr_objid, OPC_OBJTYPE_BUTXCH, 0);   // op_topo_child(parent_objid,child_type,child_index)
if (tx_channel_objid == OPC_OBJID_INVALID)    {
 eth_mac_error ("Unable to get Objid of transmitter channel.",
  OPC_NIL, OPC_NIL);
 }

/* Determine the bitrate used by the transmitter's channel. */
if (op_ima_obj_attr_get (tx_channel_objid, "data rate", &bit_rate)//这种if语句 当条件不满足时,前半句也已经执行了

 == OPC_COMPCODE_FAILURE)
 {
 eth_mac_error ("Unable to get data rate from transmitter channel.",
  OPC_NIL, OPC_NIL);
 }

/* Create an interface control information (ICI) structure for */创建ICI与上层通信
/* communication of parameters with the higher layer (LLC).  */
llc_iciptr = op_ici_create ("eth_mac_ind");  返回ici*   指向ICI函数
if (llc_iciptr == OPC_NIL)
 {
 eth_mac_error ("Unable to create ICI for communication with LLC.",
  OPC_NIL, OPC_NIL);
 }

/* Get the promiscuous mode (if all packets will be accepted) */
op_ima_obj_attr_get(mac_attr_objid, "Promiscuous Mode", &promis);   获取属性 Promiscuous Mode

/* Check if this ethernet MAC is for a port in a bridge/switch */
检查以太网mac是否支持端口的网桥/交换机节点
/* node.  In this case, the MAC will not participate in any  */
/* encapsulation/decapsulation of frames, nor will it record */
/* any statistics.            */
proc_record_handle_list_ptr = op_prg_list_create ();
oms_pr_process_discover (OPC_OBJID_INVALID, proc_record_handle_list_ptr,    //在进程注册表中寻找符合特定条件的进程
 "node objid",  OMSC_PR_OBJID,   own_node_objid,
 "protocol",  OMSC_PR_STRING,  "bridge",
 OPC_NIL);    
    
/* If the surrounding node is a bridge/switch node, the list */
/* will contain an element to indicate that another process in */
/* this node has registered itself as a bridge/switch.   */
if (op_prg_list_size (proc_record_handle_list_ptr) == 1)
 {
 mac_port_of_a_bridge_switch_node = OPC_TRUE;
 }
    
/* Deallocate process registry information.      */
while (op_prg_list_size (proc_record_handle_list_ptr))
 op_prg_list_remove (proc_record_handle_list_ptr, OPC_LISTPOS_HEAD);
op_prg_mem_free (proc_record_handle_list_ptr);

/************************************************************************/
/* This process can be simultaneously used to send/receive packets both */这个进程可以同时使用IP和IPX收发包
由于IP和IPX作为单独的协议栈实现,所以每个网络层有一对与周围模块相关联的数据流。使用OMS进程注册表来查看在这个节点中使用了一种还是两种协议栈。根据每个网络层的实现,确定输入输出的包流索引
/* from IP and IPX. Since IP and IPX are implemented as separate stacks */
/* each network layer can have a pair of streams associated with the */
/* surrounding module. Use the OMS Process Registry to find out if both */
/* or just one of the two are present in this node. For each network */
/* layer implementation that is present, determine the incoming and  */
/* outgoing packet stream index.          */
/************************************************************************/

/************************************************************************/
/*     Find out if the IPX stack is present.    */  寻找使用IPX的节点
/************************************************************************/

/* Create an instance of the List data structure.      */
proc_record_handle_list_ptr = op_prg_list_create ();

/* Discover all processes that are neighbors of the parent module and */
/* that have registered a value of 'ipx_bcast_intf' for the value of */
/* the 'protocol' attribute.           */
oms_pr_process_discover (my_objid, proc_record_handle_list_ptr,  寻找范围:当前节点的父节点内
 "node objid",    OMSC_PR_OBJID,  (op_id_parent (my_objid)),
 "protocol",    OMSC_PR_STRING, "ipx_bcast_intf",
 OPC_NIL);
 
/* For each ethernet data link implementation, there should be just one */
/* neighbor module hosting the 'ipx_bcast_intf' process. If this is  */
/* true then obtain the object ID of that neighbor module.    */
if (op_prg_list_size (proc_record_handle_list_ptr) == 1)   如果找到了符合IPX的节点
 {
 /* Else, access the single process record handle.     */
 proc_record_handle = (OmsT_Pr_Handle) op_prg_list_remove (
  proc_record_handle_list_ptr, OPC_LISTPOS_HEAD);

 /* Obtain the value of the 'protocol' attribute published by the IPX*/
 /* process.               */
 if (oms_pr_attr_get (proc_record_handle, "module objid" 获取节点id,
  OMSC_PR_OBJID, &mod_objid) == OPC_COMPCODE_FAILURE)
  {
  eth_mac_error (
   "Failed to get value of 'module objid' attr. from OMS PR.",
   OPC_NIL, OPC_NIL);
  }

 /* Determine the input and output stream indices to be used when */
 /* sending/receiving packets from the IPX network layer.   */确定输入输出流索引
 if (oms_tan_neighbor_streams_find (
  my_objid, mod_objid, &strm_from_ipx, &strm_to_ipx) ==    需用到当前节点id和符合条件的节点id
  OPC_COMPCODE_FAILURE)
  {
  eth_mac_error (
   "Failed to determine the I/P and O/P streams from and to the IPX",
   "network layer implementation.", OPC_NIL);
  }
 }

/* If there is no neighbor module hosting the ipx_bcast_intf process */
/* set the values of the I/P and O/P stream state vars. to OPC_INT_UNDEF*/
else if (op_prg_list_size (proc_record_handle_list_ptr) == 0)  如果找不到符合的节点
 {
 strm_to_ipx  = OPC_INT_UNDEF;   将输入输出流索引号设为默认
 strm_from_ipx = OPC_INT_UNDEF;
 }

/* If more than one neighbor module was found then flag the error and */
/* exit the simulation.             */
else if (op_prg_list_size (proc_record_handle_list_ptr) > 1)如果找到符合的节点多于一个
 {  
 eth_mac_error (                                                                              报错
  "Found more than one IPX Broadcast Intf. process registered in OMS PR.",
  OPC_NIL, OPC_NIL);
 }

/* Deallocate process registry information. Note that we do not  */
/* deallocate the memory referenced by the members of the process */
/* record handle list. This is because the members of this list are */
/* pointers to memory ALSO REFERENCED IN THE GLOBAL PROCESS REGISTRY*/
while (op_prg_list_size (proc_record_handle_list_ptr)) 释放链表
 op_prg_list_remove (proc_record_handle_list_ptr, OPC_LISTPOS_HEAD);
op_prg_mem_free (proc_record_handle_list_ptr);释放链表内存

/************************************************************************/
/*     Find out if the IP stack is present.    */  寻找使用IP的节点     (步骤同上)
/************************************************************************/

/* Create an instance of the List data structure.      */
proc_record_handle_list_ptr = op_prg_list_create ();

/* Discover all processes that are neighbors of the parent module and */
/* that have registered a value of 'arp' for the value of the 'protocol'*/
/* attribute.               */
oms_pr_process_discover (my_objid, proc_record_handle_list_ptr,
 "node objid",    OMSC_PR_OBJID,  (op_id_parent (my_objid)), 
 "protocol",    OMSC_PR_STRING, "arp",
 OPC_NIL);
 
/* For each ethernet data link implementation, there should be just one */
/* neighbor module hosting the 'arp' process. If this is true then  */
/* obtain the object ID of that neighbor module.      */
if (op_prg_list_size (proc_record_handle_list_ptr) == 1)
 {
 /* Else, access the single process record handle.     */
 proc_record_handle = (OmsT_Pr_Handle) op_prg_list_remove (
  proc_record_handle_list_ptr, OPC_LISTPOS_HEAD);

 /* Obtain the value of the 'module objid' attribute published by */
 /* the arp process.             */
 if (oms_pr_attr_get (proc_record_handle, "module objid",
  OMSC_PR_OBJID, &mod_objid) == OPC_COMPCODE_FAILURE)
  {
  eth_mac_error (
   "Failed to get value of 'module objid' attr. from OMS PR.",
   OPC_NIL, OPC_NIL);
  }

 /* Determine the input and output stream indices to be used when */
 /* sending/receiving packets from the IP network layer.    */
 if (oms_tan_neighbor_streams_find (
  my_objid, mod_objid, &strm_from_ip, &strm_to_ip) ==
  OPC_COMPCODE_FAILURE)
  {
  eth_mac_error (
   "Failed to determine the I/P and O/P streams from and to the IP",
   "network layer implementation.", OPC_NIL);
  }
 }

/* If there is no neighbor module hosting the ipx_bcast_intf process */
/* set the values of the I/P and O/P stream state vars. to OPC_INT_UNDEF*/
else if (op_prg_list_size (proc_record_handle_list_ptr) == 0)
 {
 strm_to_ip  = OPC_INT_UNDEF;
 strm_from_ip = OPC_INT_UNDEF;
 }

/* If more than one neighbor module was found then flag the error and */
/* exit the simulation.             */
else if (op_prg_list_size (proc_record_handle_list_ptr) > 1)
 {
 eth_mac_error (
  "Found more than one IP Addr. Res. Protocol process registered in OMS PR.",
  OPC_NIL, OPC_NIL);
 }

/* Deallocate process registry information. Note that we do not  */
/* deallocate the memory referenced by the members of the process */
/* record handle list. This is because the members of this list are */
/* pointers to memory ALSO REFERENCED IN THE GLOBAL PROCESS REGISTRY*/
while (op_prg_list_size (proc_record_handle_list_ptr))
 op_prg_list_remove (proc_record_handle_list_ptr, OPC_LISTPOS_HEAD);
op_prg_mem_free (proc_record_handle_list_ptr);

/* Schedule a self interrupt to move from the "start" state. */
/* This additional state is necessary to confirm the final MAC */
/* address if it is dynamically assigned (auto assigned).  */
op_intrpt_schedule_self (op_sim_time (), 0);  产生一个自中断

 

抱歉!评论已关闭.