📄 etherswitch.java
字号:
/*
JaNetSim --- Java Network Simulator
-------------------------------------
This software was developed at the Network Research Lab, Faculty of
Computer Science and Information Technology (FCSIT), University of Malaya.
This software may be used and distributed freely. FCSIT assumes no responsibility
whatsoever for its use by other parties, and makes no guarantees, expressed or
implied, about its quality, reliability, or any other characteristic.
We would appreciate acknowledgement if the software is used.
FCSIT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
FROM THE USE OF THIS SOFTWARE.
*/
package janetsim.component;
import janetsim.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;
public class EtherSwitch extends SimComponent implements SimCommand,AnalyzerUser,
ActionListener,Serializable {
private class Port implements Serializable {
SimComponent to_link=null;
boolean link_busy=false;
java.util.List outQ=null;
int outQ_size; //in bytes
java.util.List spq=null;
int spq_size; //in bytes
}
private class ForwardEntry implements Serializable {
long dest_mac;
SimComponent to_link=null;
//NOTE: for now, no aging is done for the forwarding entries...
}
private java.util.Random randgen;
private SimParamDouble sw_delay;
private SimParamInt sw_oqsize;
private SimParamInt sw_spqsize;
private SimParamInt sw_speed;
private SimParamDouble sw_ai;
private SimParamBool sw_name_seed;
private SimParamInt sw_log_factor;
private SimParamInt sw_frames_received;
private SimParamInt sw_dropped;
private SimParamBool sw_cpucong;
private java.util.Map sw_forward_table=null;
private java.util.Map voports;
private transient Analyzer analyzer=null;
//private events
static final int MY_RECEIVE = SimProvider.EV_PRIVATE + 1;
static final int MY_SLOT_TIME = SimProvider.EV_PRIVATE + 2;
static final int EV_AVERAGING_INTERVAL = SimProvider.EV_PRIVATE + 3;
public EtherSwitch(String aName,String aClass,Sim aSim,int locx,int locy) {
super(aName,aClass,aSim,locx,locy);
randgen=new java.util.Random();
sw_create();
}
public boolean isConnectable(SimComponent comp) {
if(!super.isConnectable(comp)) return false;
if(comp.getCompClass().equals("Link")) return true;
return false;
}
protected void neighborAdded(SimComponent comp) {
Port voport=new Port();
voport=new Port();
voport.link_busy=false;
voport.to_link=comp;
voport.outQ=new java.util.LinkedList();
voport.outQ_size=0;
voport.spq=new java.util.LinkedList();
voport.spq_size=0;
voports.put(voport.to_link,voport);
}
protected void neighborRemoved(SimComponent comp) {
voports.remove(comp);
}
public void copy(SimComponent comp) {
if(comp instanceof EtherSwitch) {
EtherSwitch theComp=(EtherSwitch)comp;
sw_delay.setValue(theComp.sw_delay.getValue());
sw_oqsize.setValue(theComp.sw_oqsize.getValue());
sw_spqsize.setValue(theComp.sw_spqsize.getValue());
sw_speed.setValue(theComp.sw_speed.getValue());
sw_ai.setValue(theComp.sw_ai.getValue());
sw_name_seed.setValue(theComp.sw_name_seed.getValue());
sw_log_factor.setValue(theComp.sw_log_factor.getValue());
}
}
public Image getImage(Component refcomp) {
if(image==null) {
image=Toolkit.getDefaultToolkit().getImage(
"images"+System.getProperty("file.separator")+"eth_switch.gif");
}
return image;
}
public void reset() {
sw_frames_received.setValue(0);
sw_frames_received.update(theSim.now());
sw_dropped.setValue(0);
sw_dropped.update(theSim.now());
sw_cpucong.setValue(false);
sw_cpucong.update(theSim.now());
sw_forward_table.clear();
java.util.Iterator i=voports.values().iterator();
while(i.hasNext()) {
Port voport=(Port)i.next();
voport.link_busy=false;
voport.outQ.clear();
voport.outQ_size=0;
voport.spq.clear();
voport.spq_size=0;
}
if(analyzer!=null) analyzer.reset();
}
public void start() {
if(sw_name_seed.getValue()==true)
randgen.setSeed(getName().hashCode());
for(int i=0;i<randgen.nextInt(100);i++) randgen.nextDouble();
double aiusec=sw_ai.getValue();
aiusec+=randgen.nextDouble()*aiusec;
theSim.enqueue(new SimEvent(EV_AVERAGING_INTERVAL,this,this,
theSim.now()+SimClock.USec2Tick(aiusec),null));
}
public void action(SimEvent e) {
switch(e.getType()) {
case MY_SLOT_TIME:
sw_proc_slot_time(e);
break;
case SimProvider.EV_RECEIVE:
sw_receive(e);
break;
case MY_RECEIVE:
sw_my_receive(e);
break;
case SimProvider.EV_READY:
sw_ready(e);
break;
case EV_AVERAGING_INTERVAL:
sw_averaging_interval();
theSim.enqueue(new SimEvent(EV_AVERAGING_INTERVAL,this,this,
theSim.now()+SimClock.USec2Tick(sw_ai.getValue()),null));
break;
}
}
////////////////////////// private methods ////////////////////////////////
private void sw_create() {
voports=new java.util.HashMap();
sw_forward_table=new java.util.HashMap();
//Initialize the parameters
long ctick=theSim.now();
sw_delay=new SimParamDouble("Delay to process a byte (uSec)",this,ctick,false,true,0);
sw_speed=new SimParamInt("Switching Speed (Mbit/s)",this,ctick,false,true,1000);
sw_oqsize=new SimParamInt("Output q_size (kbytes, -1=inf)",this,ctick,false,true,100);
sw_spqsize=new SimParamInt("Speedup q_size (kbytes, -1=inf)",this,ctick,false,true,10);
sw_ai=new SimParamDouble("Averaging Interval (usec)",this,ctick,false,true,100000.0);
sw_name_seed=new SimParamBool("Use name as seed",this,ctick,false,true,true);
sw_log_factor=new SimParamInt("Logging every (ticks) (e.g. 1, 100)",this,ctick,false,true,0);
sw_frames_received=new SimParamInt("Frames Received",this,ctick,true,false,0);
sw_frames_received.update(ctick);
sw_dropped=new SimParamInt("Frames Dropped",this,ctick,true,false,0);
sw_dropped.update(ctick);
sw_cpucong=new SimParamBool("CPU Slow Triggered",this,ctick,true,false,false);
sw_cpucong.update(ctick);
addParameter(sw_delay);
addParameter(sw_speed);
addParameter(sw_oqsize);
addParameter(sw_spqsize);
addParameter(sw_ai);
addParameter(sw_name_seed);
addParameter(sw_log_factor);
addParameter(sw_frames_received);
addParameter(sw_dropped);
addParameter(sw_cpucong);
}
private void sw_averaging_interval() {
//nothing here for now...
}
private void sw_proc_slot_time(SimEvent e) {
//performing the demux_spq operation
Port voport=(Port)e.getParams();
EtherFrame frame;
long ticks;
//check for cpu congestion (just mark it, no action taken)
if(voport.spq_size > (sw_spqsize.getValue()*1024)) {
sw_cpucong.setValue(true);
sw_cpucong.update(theSim.now());
}
//voport.spq must not be empty here!
if(voport.spq.isEmpty()) {
System.out.println("Warning: sw_proc_slot_time called with spq empty!!");
return;
}
frame=(EtherFrame)voport.spq.remove(0);
voport.spq_size -= (frame.length()>>3);
if((voport.outQ_size + (frame.length()>>3) < sw_oqsize.getValue() * 1024)
|| (sw_oqsize.getValue() == -1)) {
voport.outQ.add(frame);
voport.outQ_size += (frame.length() >> 3);
}
else {
sw_dropped.setValue(sw_dropped.getValue()+1,theSim.now(),sw_log_factor.getValue());
frame=null;
}
//output frame to link if possible
if(!voport.outQ.isEmpty() && !voport.link_busy) {
voport.link_busy=true;
sw_schedule_output(voport);
}
//schedule next proc_slot if needed
if(!voport.spq.isEmpty()) {
frame=(EtherFrame)voport.spq.get(0);
ticks=SimClock.USec2Tick(frame.length() / (double)sw_speed.getValue());
theSim.enqueue(new SimEvent(MY_SLOT_TIME,this,this,theSim.now()+ticks,voport));
}
}
private void sw_ready(SimEvent e) {
Port voport=(Port)voports.get(e.getSource());
if(voport!=null) {
if(voport.link_busy) {
voport.link_busy=false;
if(!voport.outQ.isEmpty()) {
voport.link_busy=true;
sw_schedule_output(voport);
}
}
}
}
private void sw_schedule_output(Port voport) {
EtherFrame frame=(EtherFrame)voport.outQ.remove(0);
voport.outQ_size -= (frame.length()>>3);
theSim.enqueue(new SimEvent(SimProvider.EV_RECEIVE,this,
voport.to_link,theSim.now(),frame));
//inform analyzer
if(analyzer!=null) analyzer.update(frame,this,voport.to_link);
}
private void sw_receive(SimEvent e) {
EtherFrame frame=(EtherFrame)e.getParams();
SimComponent src=(SimComponent)e.getSource();
long ticks;
ticks=SimClock.USec2Tick(sw_delay.getValue() * (frame.length()>>3));
theSim.enqueue(new SimEvent(MY_RECEIVE,src,this,
theSim.now()+ticks,e.getParams()));
//update frames count
sw_frames_received.setValue(sw_frames_received.getValue()+1,theSim.now(),sw_log_factor.getValue());
//inform analyzer
if(analyzer!=null) analyzer.update(frame,src,this);
}
private void sw_broadcast(EtherFrame frame,SimComponent src) {
long ticks;
java.util.Iterator i=voports.values().iterator();
while(i.hasNext()) {
Port voport=(Port)i.next();
if(voport.to_link==src) continue; //skip the source port
voport.spq.add(frame);
voport.spq_size+= (frame.length()>>3);
if(voport.spq.size()==1) { //must schedule a processing slot if spq previously empty
ticks=SimClock.USec2Tick(frame.length() / (double)sw_speed.getValue());
theSim.enqueue(new SimEvent(MY_SLOT_TIME,this,this,theSim.now()+ticks,voport));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -