/* ###############################################
802.11のシミュレーションプログラム IEEE802_11.c
作成者:伊藤 隆範
作成日:2005.7.15
更新日:2005.8.3
############################################### */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
//#define MAX 2147483647.0 /*乱数最大値(UNIX用)*/
//#define MAX 32767.0 /*Windows*/
#define SIM_TIME 300000000 /*シミュレーション時間(スロット)*/
#define LOAD_START 0.10 /*負荷*/
#define LOAD_END 1.00
#define LOAD_INTERVAL 0.10
#define HOSEI 0.001
#define N 16 /*ノード数*/
#define MAX_RETRANSMIT 6 /*最大再送回数の基準値*/
#define BUFFER_SIZE 10 /*バッファサイズ(パケット数)*/
#define DIFS_TIME 2 /*DIFSの時間(スロット数)*/
/* そのバッファにパケットがあるかないか(state_bで使用) */
#define EXIST 1 /*パケット有り*/
#define EMPTY 0 /*パケット無し*/
/* ノードの状態(stateで使用) */
#define IDLE_S 0 /*バッファにパケットがない状態*/
#define DIFS_S 1 /*DIFS待ち状態*/
#define BACKOFF_S 2 /*バックオフ待ち状態*/
#define TRANSMIT_S 3 /*送信状態(ノード)*/
#define RECEIVE_S 4 /*受信状態(ノード)*/
#define NAV_S 5 /*RTS/CTSを受信し送信禁止状態*/
#define NON -1 /*なにも値がないことを表す*/
/* ###############################################
構造体の宣言
############################################### */
/* 構造体1: パケット */
struct PACKET {
int state_b; /*そのバッファにパケットがあるかないか(EXIST,EMPTY)*/
int hop; /*これまでの通過ホップ*/
int hop_all; /*あて先までのホップ数(本来知らないが評価のため生成時点で与える)*/
int source_ip; /*送信ノード(IP層)*/
int dest_ip; /*あて先ノード(IP層)*/
int route[N]; /*通過するノード(経路)*/
};
/* 構造体2: ノード */
struct NODE {
int no_node; /*ノード番号*/
int state; /*ノードの状態(IDLE_S、DIFS_S、BACKOFF_S、TRANSMIT_S、RECEIVE_S、NAV_S)*/
int pre_state; /*一つ前のノードの状態(IDLE_S、DIFS_S、BACKOFF_S、TRANSMIT_S、RECEIVE_S、NAV_S)*/
int num_arrive; /*現スロットでノードに到着したパケット数*/
int count_difs; /*ノードがDIFS_Sになってからの経過スロット数*/
int count_t; /*ノードがTRANSMIT_Sになってからの経過スロット数*/
int check_count; /*ノードがRTS、CTS、DATA、ACKを全スロット受信したか否かの確認カウント*/
int nav; /*network allocation vector(送信禁止期間)のスロット数*/
int num_connect_node; /*隣接ノード数*/
int connect_node[N]; /*隣接ノードのノード番号*/
int dest_mac; /*キューの先頭のパケットのあて先ノード*/
int source_mac; /*自分があて先である場合の送信ノード*/
int num_retransmit; /*再送回数*/
int num_max_retransmit; /*最大再送回数*/
int backoff; /*バックオフ時間(スロット数)*/
int num_buffer; /*バッファにたまっているパケット数*/
struct PACKET buffer[BUFFER_SIZE]; /*送信バッファ、パケットの情報を格納*/
struct PACKET buffer_receive; /*受信バッファ、パケットの情報を一時的に格納*/
struct PACKET buffer_mypacket; /*自ノードで発生したパケットの情報を一時的に格納*/
};
/* ###############################################
変数の宣言
############################################### */
struct NODE node[N]; /*N個のノードを生成*/
double load; /*入力負荷*/
/*---評価用のカウンタ---*/
int send_p; /*送信(発生)したパケット数(send=receive+drop+remain)*/
int receive_p; /*受信(最終)したパケット数*/
int drop_p; /*ネットワークの途中で棄却されたパケット数*/
int remain_p; /*ネットワークに残ったパケット数*/
/*あて先までのホップ数は1〜6なので添え字をそのままあて先までのホップ数とする*/
int send_p_hop_all[7]; /*あて先までのホップ数毎の送信(発生)したパケット数(send=receive+drop+remain)*/
int receive_p_hop_all[7]; /*あて先までのホップ数毎の受信(最終)したパケット数*/
int drop_p_hop_all[7]; /*あて先までのホップ数毎のネットワークの途中で棄却されたパケット数*/
int remain_p_hop_all[7]; /*あて先までのホップ数毎のネットワークに残ったケット数*/
/*通過ホップ数は0〜5なので添え字をそのまま通過ホップ数とする*/
int send_p_hop[6]; /*通過ホップ数毎の途中のノードで送信したパケット数(send=receive+drop+remain)*/
int receive_p_hop[6]; /*通過ホップ数毎の途中のノードで受信(送信成功)したパケット数*/
int drop_p_hop[6]; /*通過ホップ数毎の途中のノードで棄却(送信失敗)したパケット数*/
int remain_p_hop[6]; /*通過ホップ数毎の途中のノードに残ったパケット数*/
/*パケットを棄却するときの、バッファあふれor最大再送回数超えの割合*/
int buffer_overflow; /*バッファあふれ数*/
int excess_retransmission; /*最大再送回数超え数*/
double rate_buffer_overflow; /*バッファあふれで棄却する割合*/
double rate_excess_retransmission; /*最大再送回数超えで棄却する割合*/
/*各ノードでいくつパケットが発生しているorあて先になるか*/
int gene_num_packet[N]; /*各ノードでいくつパケットが発生しているか*/
int dest_num_packet[N]; /*各ノードがあて先になる数*/
/*---特性評価のデータ---*/
double success_p; /*パケット到達率(receive/send)*/
double success_p_hop_all[7]; /*あて先までのホップ数毎のパケット到達率(receive/send)*/
double success_p_hop[6]; /*通過ホップ数毎のネットワーク内のノードにおける送信成功率(receive/send)*/
double loss_p; /*パケット棄却率(drop/send)*/
double loss_p_hop_all[7]; /*あて先までのホップ数毎のパケット棄却率(drop/send)*/
double loss_p_hop[6]; /*通過ホップ毎のネットワーク内のノードにおけるパケット棄却率(drop/send)*/
/* ###############################################
関数のプロトタイプ宣言
関数1: 乱数発生関数(1未満の乱数を返す,0<=x<1)
関数2: バックオフ時間を計算し返す(再送回数に応じた)
関数3: ポアソン過程(入力負荷load)で全てのノードでパケットが発生する
関数4: 経路を与える関数(送信ノードとあて先ノードから)
関数5: パケットを送信バッファに格納
関数6: 全てのノードの状態を初期化
関数7: 指定されたノードの状態を初期化
関数8: 指定されたノードの送信バッファを初期化
関数9: 指定されたノードの受信バッファを初期化
関数10: 指定されたノードの自ノードからのパケットを格納するバッファを初期化
関数11: 全てのノードの隣接ノード数とノード番号を初期化
関数12: 全てのノードでパケットを受信する
関数13: ノードの遷移1
関数14: ノードの遷移2
関数15: 指定されたノードのキューを一つずらす
関数16: 特性評価のためのカウンタやデータを初期化
関数17: Output
関数18: ネットワークに残っているパケットをカウント
関数: ノードの状態を表示する
############################################### */
double myrand();
int cal_backoff(int);
void newpacket_generation();
void route_xy(int, int);
void enqueue_packet();
void init_allnode();
void init_node(int);
void init_buffer(int);
void init_buffer_receive(int);
void init_buffer_mypacket(int);
void init_connect();
void receive_packet();
void transition_node1();
void transition_node2();
void shift_queue(int);
void init_count();
void output();
void count_remain();
void testnodestate();
/* ###############################################
関数の定義
############################################### */
/* 関数1: 乱数発生関数(1未満の乱数を返す,0<=x<1)
引数 なし
戻値 1未満の乱数(x) */
double myrand(){
double x;
x=(double)(lrand48()/2147483647.0); /*UNIX用*/
// x=(double)(rand()/32767.0); /*Windows用*/
if(x==1.0){ /*たまにxが1になる。1未満を返したいので*/
x=0.99999;
}
return(x);
}
/* 関数2: バックオフ時間を計算し返す(再送回数に応じた)
引数 再送回数(x)
戻値 バックオフ時間(スロット数)(z) */
int cal_backoff(int x){
int i, y, z;
double r;
y=32; /*CWサイズのminは32,maxは1023*/
if(x>=5){
x=5;
}
for(i=0; i<x; i++){
y*=2;
}
r=myrand();
// printf("%d,",y);
// printf("%f,",r);
z=(int)(r*y);
z+=1; /*0〜31を1〜32にする.初めからCW=0はプログラム上問題有り*/
// printf("%d\n",z);
return(z);
}
/* 関数3: ポアソン過程(入力負荷load)で全てのノードでパケットが発生する
引数 なし
戻値 なし */
void newpacket_generation(){
int i;
double rand_rate;
for(i=0; i<N; i++){
rand_rate=(double)myrand(); /*1未満の乱数発生*/
if(rand_rate<=(d