OPNET學習筆記之simple_source模塊

 

simple_source模塊的功能是按照配置產生包,包括不同的包格式和產生速率,也是比較簡單的進程模型。

參考了《opnet process model:simple_source分析》http://hi.baidu.com/ebinghaus/blog/item/c7cade9228876c83a877a405.html

  該模塊有4個local statistic,注意有5個model attribute,分別是Packet Interarrival Time,Packet Size,Packet Format,Start Time,Stop Time,這些是在使用該模塊時需要配置的,當然也可以使用默認配置。

狀態機也很簡單:

在header block中定義了

/* Include files.     */
#include <oms_dist_support.h>  //注意該模塊使用了外部文件《oms_dist_support》和《oms_string_support》

/* Special attribute values.  */
#define  SSC_INFINITE_TIME  -1.0    //定義無窮大時間爲-1

/* Interrupt code values.   */  //注意這裏的中斷代碼是自定義的,爲了在產生自中斷是使用
#define  SSC_START    0
#define  SSC_GENERATE   1
#define  SSC_STOP    2

/* Node configuration constants. */
#define  SSC_STRM_TO_LOW   0    //發送的stream index,默認的,該模塊只有一個stream連接,所以不需要動態獲取stream index

/* Macro definitions for state  transitions.*/   //轉換條件爲中斷代碼是自定義的常量:

#define  START    (intrpt_code == SSC_START)
#define  DISABLED   (intrpt_code == SSC_STOP)
#define  STOP    (intrpt_code == SSC_STOP)
#define  PACKET_GENERATE  (intrpt_code == SSC_GENERATE)

/* Function prototypes.    */
static void   ss_packet_generate (void);  //產生包的函數,在function block中定義

 

一,INIT的入口代碼:

/* At this initial state, we read the values of source attributes */
/* and schedule a selt interrupt that will indicate our start time */
/* for packet generation.           */

/* Obtain the object id of the surrounding module.     */
own_id = op_id_self ();        //首先得到surrounding objid,應該是自己的objid,後面根據objid獲取對象的屬性

/* Read the values of the packet generation parameters, i.e. the */
/* attribute values of the surrounding module.      */

//用op_ima_obj_attr_get()得到對象的屬性的值,是產生包的參數。注意interarrival_str和size_str是臨時變量,還是char數組類型。
op_ima_obj_attr_get (own_id, "Packet Interarrival Time", interarrival_str);
op_ima_obj_attr_get (own_id, "Packet Size",              size_str);
op_ima_obj_attr_get (own_id, "Packet Format",            format_str);
op_ima_obj_attr_get (own_id, "Start Time",               &start_time);
op_ima_obj_attr_get (own_id, "Stop Time",                &stop_time);

/* Load the PDFs that will be used in computing the packet   */
/* interarrival times and packet sizes.        */

//裝入PDF,用於前兩個參數,得到包產生和包大小的分佈,函數是oms_dist_load_from_string(),這樣很方便的使用string類型的參數。
//獲得的是分佈函數的句柄,注意兩個句柄都是state variable,類型爲Omst_dist_handle。

interarrival_dist_ptr = oms_dist_load_from_string (interarrival_str);
pksize_dist_ptr       = oms_dist_load_from_string (size_str);

/* Verify the existence of the packet format to be used for   generated packets. */
if (strcmp (format_str, "NONE") == 0)  //檢查是否是無格式包
 {
 /* We will generate unformatted packets. Set the flag.   */
 generate_unformatted = OPC_TRUE;
 }
else
 {
 /* We will generate formatted packets. Turn off the flag.  */
 generate_unformatted = OPC_FALSE;  //不是無格式包

 /* Get the list of all available packet formats.    */

//用prg_tfile_name_list_get()得到所有可用的包格式
 pk_format_names_lptr = prg_tfile_name_list_get (PrgC_Tfile_Type_Packet_Format);

 /* Search the list for the requested packet format.    */
 format_found = OPC_FALSE;
 for (i = prg_list_size (pk_format_names_lptr); ((format_found == OPC_FALSE) && (i > 0)); i--)
  {
  /* Access the next format name and compare with requested format name */
  found_format_str = (char *) prg_list_access (pk_format_names_lptr, i - 1);
  if (strcmp (found_format_str, format_str) == 0)
   format_found = OPC_TRUE;  //找到了需求的包格式
  }

    if (format_found == OPC_FALSE)
  {
  /* The requested format does not exist. Generate unformatted packets.     */
  generate_unformatted = OPC_TRUE;
 
  /* Display an appropriate warning.       */
  op_prg_odb_print_major ("Warning from simple packet generator model (simple_source):",
        "The specified packet format", format_str,
        "is not found. Generating unformatted packets instead.", OPC_NIL);
  }

 /* Destroy the lits and its elements since we don't need it  */
 /* anymore.              */
 prg_list_free (pk_format_names_lptr);
 prg_mem_free  (pk_format_names_lptr);
 } 
 
/* Make sure we have valid start and stop times, i.e. stop time is  not earlier than start time. */
if ((stop_time <= start_time) && (stop_time != SSC_INFINITE_TIME))  //開始/結束時間不合法,設置開始仿真時間爲無窮大
 {
 /* Stop time is earlier than start time. Disable the source. */
 start_time = SSC_INFINITE_TIME;

 /* Display an appropriate warning.        */
 op_prg_odb_print_major ("Warning from simple packet generator model (simple_source):",
       "Although the generator is not disabled (start time is set to a finite value),",
       "a stop time that is not later than the start time is specified.",
       "Disabling the generator.", OPC_NIL);
 }

/* Schedule a self interrupt that will indicate our start time for */
/* packet generation activities. If the source is disabled,   */
/* schedule it at current time with the appropriate code value.  */

//產生自中斷,以指示開始產生包的時間,如果停止產生包時刻小於開始產生包的時刻(這時開始產生包的時間是無限大)在當前仿真時刻產生中斷號爲SSC_STOP中斷
if (start_time == SSC_INFINITE_TIME)
 {
 op_intrpt_schedule_self (op_sim_time (), SSC_STOP);  //馬上給出自中斷
 }
else
 {
 op_intrpt_schedule_self (start_time, SSC_START);   //自中斷,在開始時間,中斷號爲SSC_START

 /* In this case, also schedule the interrupt when we will stop */
 /* generating packets, unless we are configured to run until */
 /* the end of the simulation.         */
 if (stop_time != SSC_INFINITE_TIME)
  {
  op_intrpt_schedule_self (stop_time, SSC_STOP);  //當結束時間不是無限大時,在結束時間產生自中斷,中斷號爲SSC_STOP
  }
 
 next_intarr_time = oms_dist_outcome (interarrival_dist_ptr);  //通過分佈函數句柄計算產生下一個包的時間間隔,這裏是state variable

 /* Make sure that interarrival time is not negative. In that case it will be set to 0.*/
 if (next_intarr_time <0)
  {
  next_intarr_time = 0.0;  //保證間隔時間不小於0
  }

 }

/* Register the statistics that will be maintained by this model. */

//註冊局部統計量,返回局部統計量的句柄
bits_sent_hndl      = op_stat_reg ("Generator.Traffic Sent (bits/sec)",   OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
packets_sent_hndl   = op_stat_reg ("Generator.Traffic Sent (packets/sec)",  OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
packet_size_hndl    = op_stat_reg ("Generator.Packet Size (bits)",              OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
interarrivals_hndl  = op_stat_reg ("Generator.Packet Interarrival Time (secs)", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);

 

二,由於初始狀態是非強制狀態,進程執行完入口代碼後,停留在該狀態等待中斷觸發轉移狀態,仿真時刻到10s(屬性start_time設置的值)時將產生中斷號爲SSC_START中斷,中斷產生後將首先執行當前狀態的出口代碼,初始狀態的出口代碼如下:
intrpt_code = op_intrpt_code ();  //得到當前的中斷代碼

這時條件START滿足,進程將從初始狀態轉換到generate狀態,轉移時首先執行轉移函數ss_packet_generate (void),在function block中定義的轉移函數如下:

 

static void ss_packet_generate (void)
 {
 Packet*    pkptr;
 double    pksize;

 

 /** This function creates a packet based on the packet generation  **/
 /** specifications of the source model and sends it to the lower layer. **/
 FIN (ss_packet_generate ());

 

 /* Generate a packet size outcome.     */
 pksize = (double) ceil (oms_dist_outcome (pksize_dist_ptr));  //通過分佈函數句柄得到包大小,再通過ceil()函數向上舍入,得到包大小
 
 /* Create a packet of specified format and size. */
 if (generate_unformatted == OPC_TRUE)
  {
  /* We produce unformatted packets. Create one. */
  pkptr = op_pk_create (pksize);            //使用op_pk_creat()函數產生無格式包
  }
 else
  {
  /* Create a packet with the specified format. */
  pkptr = op_pk_create_fmt (format_str);      //使用op_pk_creat_fmt()函數產生有格式包
  op_pk_total_size_set (pkptr, pksize);        //置有格式包的總大小
  }

 

 /* Update the packet generation statistics.   */  //通過局部統計量句柄更新統計量,注意xxx/sec的量都是在更新後馬上清零
 op_stat_write (packets_sent_hndl, 1.0);
 op_stat_write (packets_sent_hndl, 0.0);
 op_stat_write (bits_sent_hndl, (double) pksize);
 op_stat_write (bits_sent_hndl, 0.0);
 op_stat_write (packet_size_hndl, (double) pksize);
 op_stat_write (interarrivals_hndl, next_intarr_time);

 

 /* Send the packet via the stream to the lower layer. */
 op_pk_send (pkptr, SSC_STRM_TO_LOW);    //發送包到定義好的stream index,默認爲0

 

 FOUT;
 } 

 

三, 執行完轉移函數後將跳到generate狀態,並首先執行入口代碼,如下:

/* At the enter execs of the "generate" state we schedule the  */
/* arrival of the next packet.          */
next_intarr_time = oms_dist_outcome (interarrival_dist_ptr);  //通過分佈函數句柄得到下一個包的產生時間間隔

 

/* Make sure that interarrival time is not negative. In that case it will be set to 0.*/
if (next_intarr_time <0)
 {
 next_intarr_time = 0;
 }

//在當前時間+間隔時間後,產生自中斷,中斷號爲SSC_GENERATE,注意返回值爲Evhandle類型

next_pk_evh = op_intrpt_schedule_self (op_sim_time () + next_intarr_time, SSC_GENERATE);

 

四,執行完入口代碼後,進程將停留在generate狀態等待中斷,當下一箇中斷髮生,進行狀態轉換,首先執行generate狀態的出口代碼:

intrpt_code = op_intrpt_code ();  //得到中斷號

然後判斷轉移條件。

如果是STOP,執行stop狀態的入口代碼:

/* When we enter into the "stop" state, it is the time for us to */
/* stop generating traffic. We simply cancel the generation of the */
/* next packet and go into a silent mode by not scheduling anything */
/* else.               */
if (op_ev_valid (next_pk_evh) == OPC_TRUE)    //如果下一個事件仍然有效,就取消該事件,使用事件句柄
 {
 op_ev_cancel (next_pk_evh);
 }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章