bdi-network-resilience

Details

diff --git a/network-resilience/APDescription.txt b/network-resilience/APDescription.txt
new file mode 100644
index 0000000..f5daa80
--- /dev/null
+++ b/network-resilience/APDescription.txt
@@ -0,0 +1 @@
+( ap-description  :name "143.54.13.160:1099/JADE" :ap-services (set ( ap-service  :name fipa.mts.mtp.http.std :type fipa.mts.mtp.http.std :addresses (sequence http://IngridNunes-PC.inf.ufrgs.br:7778/acc))))
diff --git a/network-resilience/MTPs-Main-Container.txt b/network-resilience/MTPs-Main-Container.txt
new file mode 100644
index 0000000..08cdd31
--- /dev/null
+++ b/network-resilience/MTPs-Main-Container.txt
@@ -0,0 +1 @@
+http://IngridNunes-PC.inf.ufrgs.br:7778/acc
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/AnomalyDetectionCapability.java b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/AnomalyDetectionCapability.java
index 9c22acf..fdca759 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/AnomalyDetectionCapability.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/AnomalyDetectionCapability.java
@@ -23,61 +23,115 @@ package br.ufrgs.inf.bdinetr.agent;
 
 import java.util.Set;
 
+import bdi4jade.annotation.Parameter;
+import bdi4jade.annotation.Parameter.Direction;
 import bdi4jade.belief.Belief;
 import bdi4jade.belief.PropositionalBelief;
+import bdi4jade.core.Capability;
 import bdi4jade.core.GoalUpdateSet;
-import bdi4jade.reasoning.AbstractReasoningStrategy;
+import bdi4jade.goal.GoalTemplateFactory;
+import bdi4jade.plan.DefaultPlan;
+import bdi4jade.plan.Plan;
+import bdi4jade.plan.planbody.BeliefGoalPlanBody;
 import bdi4jade.reasoning.OptionGenerationFunction;
 import br.ufrgs.inf.bdinetr.domain.AnomalyDetection;
+import br.ufrgs.inf.bdinetr.domain.Ip;
+import br.ufrgs.inf.bdinetr.domain.Link;
 import br.ufrgs.inf.bdinetr.domain.logic.IpPreposition.Anomalous;
 import br.ufrgs.inf.bdinetr.domain.logic.IpPreposition.Benign;
+import br.ufrgs.inf.bdinetr.domain.logic.IpPreposition.OverUsageCause;
 import br.ufrgs.inf.bdinetr.domain.logic.IpPreposition.Restricted;
+import br.ufrgs.inf.bdinetr.domain.logic.LinkProposition.RegularUsage;
 
 /**
  * @author Ingrid Nunes
  */
-public class AnomalyDetectionCapability extends RouterAgentCapability {
+public class AnomalyDetectionCapability extends RouterAgentCapability implements
+		OptionGenerationFunction {
+
+	public class AnalyseLinkStatistics extends BeliefGoalPlanBody {
+		private static final long serialVersionUID = -3493377510830902961L;
+
+		private Link link;
 
-	private class ReasoningStrategy extends AbstractReasoningStrategy implements
-			OptionGenerationFunction {
 		@Override
-		public void generateGoals(GoalUpdateSet goalUpdateSet) {
-			Set<Belief<?, ?>> anomalousIpBeliefs = getBeliefBase()
-					.getBeliefsByType(Anomalous.class);
-			for (Belief<?, ?> belief : anomalousIpBeliefs) {
-				PropositionalBelief<Anomalous> anomalous = (PropositionalBelief<Anomalous>) belief;
-				if (anomalous.getValue()) {
-					goal(new Restricted(anomalous.getName().getIp()), true);
-					goal(new Benign(anomalous.getName().getIp()));
-				}
+		public void execute() {
+			Set<Ip> outliers = role.detectIntrusion(link);
+			for (Ip outlier : outliers) {
+				belief(new Anomalous(outlier), true);
+				belief(new Benign(outlier), null);
+				belief(new OverUsageCause(outlier, link), true);
 			}
 
-			Set<Belief<?, ?>> restrictedBeliefs = getBeliefBase()
-					.getBeliefsByType(Restricted.class);
-			for (Belief<?, ?> belief : restrictedBeliefs) {
-				PropositionalBelief<Restricted> restricted = (PropositionalBelief<Restricted>) belief;
-				if (restricted.getValue()) {
-					PropositionalBelief<Anomalous> anomalous = (PropositionalBelief<Anomalous>) getBeliefBase()
+			boolean exists = false;
+			Set<Belief<?, ?>> overUsageCauseBeliefs = getBeliefBase()
+					.getBeliefsByType(OverUsageCause.class);
+			for (Belief<?, ?> belief : overUsageCauseBeliefs) {
+				PropositionalBelief<OverUsageCause> overUsageCause = (PropositionalBelief<OverUsageCause>) belief;
+				assert overUsageCause.getValue();
+
+				if (link.equals(overUsageCause.getName().getLink())) {
+					PropositionalBelief<Restricted> restricted = (PropositionalBelief<Restricted>) getBeliefBase()
 							.getBelief(
-									new Anomalous(restricted.getName().getIp()));
-					if (anomalous != null && !anomalous.getValue()) {
-						goal(new Restricted(restricted.getName().getIp()),
-								false);
+									new Restricted(overUsageCause.getName()
+											.getIp()));
+					if (restricted == null || !restricted.getValue()) {
+						exists = true;
+						break;
 					}
 				}
 			}
+			belief(new RegularUsage(link), !exists);
+		}
+
+		@Parameter(direction = Direction.IN)
+		public void setBeliefName(RegularUsage regularUsage) {
+			this.link = regularUsage.getLink();
 		}
 	}
 
 	private static final long serialVersionUID = -1705728861020677126L;
 
+	@bdi4jade.annotation.Plan
+	private Plan analyseLinkStatistics;
 	@bdi4jade.annotation.TransientBelief
 	private final AnomalyDetection role;
 
 	public AnomalyDetectionCapability(AnomalyDetection anomalyDetection) {
 		this.role = anomalyDetection;
-		ReasoningStrategy strategy = new ReasoningStrategy();
-		setOptionGenerationFunction(strategy);
+
+		setOptionGenerationFunction(this);
+
+		analyseLinkStatistics = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfType(RegularUsage.class),
+				AnalyseLinkStatistics.class);
+	}
+
+	@Override
+	public void generateGoals(GoalUpdateSet goalUpdateSet) {
+		Set<Belief<?, ?>> anomalousIpBeliefs = getBeliefBase()
+				.getBeliefsByType(Anomalous.class);
+		for (Belief<?, ?> belief : anomalousIpBeliefs) {
+			PropositionalBelief<Anomalous> anomalous = (PropositionalBelief<Anomalous>) belief;
+			if (anomalous.getValue()) {
+				PropositionalBelief<Restricted> restricted = (PropositionalBelief<Restricted>) getBeliefBase()
+						.getBelief(new Restricted(anomalous.getName().getIp()));
+				if (restricted == null || !restricted.getValue()) {
+					goalUpdateSet.generateGoal(createGoal(new Restricted(
+							anomalous.getName().getIp()), true));
+					goalUpdateSet.generateGoal(createGoal(new Benign(anomalous
+							.getName().getIp())));
+				}
+			}
+		}
+	}
+
+	@Override
+	public void setCapability(Capability capability) {
+		if (!this.equals(capability)) {
+			throw new IllegalArgumentException(
+					"This reasoning strategy is already associated with another capability.");
+		}
 	}
 
 }
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/ClassifierCapability.java b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/ClassifierCapability.java
index 5087f32..e505595 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/ClassifierCapability.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/ClassifierCapability.java
@@ -23,44 +23,110 @@ package br.ufrgs.inf.bdinetr.agent;
 
 import java.util.Set;
 
+import bdi4jade.annotation.Parameter;
+import bdi4jade.annotation.Parameter.Direction;
 import bdi4jade.belief.Belief;
 import bdi4jade.belief.PropositionalBelief;
+import bdi4jade.core.Capability;
 import bdi4jade.core.GoalUpdateSet;
-import bdi4jade.reasoning.AbstractReasoningStrategy;
+import bdi4jade.goal.BeliefPresentGoal;
+import bdi4jade.goal.GoalTemplateFactory;
+import bdi4jade.plan.DefaultPlan;
+import bdi4jade.plan.Plan;
+import bdi4jade.plan.planbody.BeliefGoalPlanBody;
 import bdi4jade.reasoning.OptionGenerationFunction;
 import br.ufrgs.inf.bdinetr.domain.Classifier;
+import br.ufrgs.inf.bdinetr.domain.Flow;
+import br.ufrgs.inf.bdinetr.domain.Ip;
 import br.ufrgs.inf.bdinetr.domain.logic.FlowPreposition.Threat;
 import br.ufrgs.inf.bdinetr.domain.logic.FlowPreposition.ThreatResponded;
+import br.ufrgs.inf.bdinetr.domain.logic.IpPreposition.Anomalous;
+import br.ufrgs.inf.bdinetr.domain.logic.IpPreposition.Benign;
 
 /**
  * @author Ingrid Nunes
  */
-public class ClassifierCapability extends RouterAgentCapability {
+public class ClassifierCapability extends RouterAgentCapability implements
+		OptionGenerationFunction {
+
+	public class AnalyseIPFlows extends BeliefGoalPlanBody {
+		private static final long serialVersionUID = -3493377510830902961L;
+
+		private Ip ip;
 
-	private class ReasoningStrategy extends AbstractReasoningStrategy implements
-			OptionGenerationFunction {
 		@Override
-		public void generateGoals(GoalUpdateSet goalUpdateSet) {
+		public void execute() {
+			role.turnFlowExporterOn();
+			Set<Flow> malicious = role.classifyFlows(ip);
+
+			for (Flow flow : malicious) {
+				belief(new Threat(flow), true);
+			}
+
+			boolean exists = false;
 			Set<Belief<?, ?>> threatBeliefs = getBeliefBase().getBeliefsByType(
 					Threat.class);
 			for (Belief<?, ?> belief : threatBeliefs) {
 				PropositionalBelief<Threat> threat = (PropositionalBelief<Threat>) belief;
-				if (threat.getValue()) {
-					goal(new ThreatResponded(threat.getName().getFlow()), true);
+				assert threat.getValue();
+
+				if (ip.equals(threat.getName().getFlow().getDstIp())) {
+					exists = true;
+					break;
 				}
 			}
+			belief(new Benign(ip), !exists);
+		}
+
+		@Parameter(direction = Direction.IN)
+		public void setBeliefName(Benign benign) {
+			this.ip = benign.getIp();
 		}
 	}
 
 	private static final long serialVersionUID = -1705728861020677126L;
 
+	@bdi4jade.annotation.Plan
+	private Plan analyseIpFlows;
 	@bdi4jade.annotation.TransientBelief
 	private final Classifier role;
 
 	public ClassifierCapability(Classifier classifier) {
 		this.role = classifier;
-		ReasoningStrategy strategy = new ReasoningStrategy();
-		setOptionGenerationFunction(strategy);
+
+		setOptionGenerationFunction(this);
+
+		analyseIpFlows = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfType(Benign.class),
+				AnalyseIPFlows.class) {
+			public boolean isContextApplicable(bdi4jade.goal.Goal goal) {
+				BeliefPresentGoal<Benign> bg = (BeliefPresentGoal<Benign>) goal;
+				PropositionalBelief<Anomalous> anomalous = (PropositionalBelief<Anomalous>) getBeliefBase()
+						.getBelief(new Anomalous(bg.getBeliefName().getIp()));
+				return (anomalous != null && anomalous.getValue());
+			};
+		};
+	}
+
+	@Override
+	public void generateGoals(GoalUpdateSet goalUpdateSet) {
+		Set<Belief<?, ?>> threatBeliefs = getBeliefBase().getBeliefsByType(
+				Threat.class);
+		for (Belief<?, ?> belief : threatBeliefs) {
+			PropositionalBelief<Threat> threat = (PropositionalBelief<Threat>) belief;
+			if (threat.getValue()) {
+				goalUpdateSet.generateGoal(createGoal(new ThreatResponded(
+						threat.getName().getFlow()), true));
+			}
+		}
+	}
+
+	@Override
+	public void setCapability(Capability capability) {
+		if (!this.equals(capability)) {
+			throw new IllegalArgumentException(
+					"This reasoning strategy is already associated with another capability.");
+		}
 	}
 
 }
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/LinkMonitorCapability.java b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/LinkMonitorCapability.java
index f8181f6..b614893 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/LinkMonitorCapability.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/LinkMonitorCapability.java
@@ -27,8 +27,8 @@ import java.util.Set;
 import bdi4jade.belief.Belief;
 import bdi4jade.belief.PropositionalBelief;
 import bdi4jade.belief.TransientBelief;
+import bdi4jade.core.Capability;
 import bdi4jade.core.GoalUpdateSet;
-import bdi4jade.reasoning.AbstractReasoningStrategy;
 import bdi4jade.reasoning.BeliefRevisionStrategy;
 import bdi4jade.reasoning.OptionGenerationFunction;
 import br.ufrgs.inf.bdinetr.domain.Link;
@@ -42,53 +42,7 @@ import br.ufrgs.inf.bdinetr.domain.logic.LinkProposition.RegularUsage;
  * @author Ingrid Nunes
  */
 public class LinkMonitorCapability extends RouterAgentCapability implements
-		Observer {
-
-	private class ReasoningStrategy extends AbstractReasoningStrategy implements
-			BeliefRevisionStrategy, OptionGenerationFunction {
-		@Override
-		public void generateGoals(GoalUpdateSet goalUpdateSet) {
-			Set<Belief<?, ?>> overUsageBeliefs = getBeliefBase()
-					.getBeliefsByType(OverUsage.class);
-			for (Belief<?, ?> belief : overUsageBeliefs) {
-				PropositionalBelief<OverUsage> overUsage = (PropositionalBelief<OverUsage>) belief;
-				if (overUsage.getValue()) {
-					PropositionalBelief<AttackPrevented> attackPrevented = (PropositionalBelief<AttackPrevented>) getBeliefBase()
-							.getBelief(
-									new AttackPrevented(overUsage.getName()
-											.getLink()));
-					if (attackPrevented == null || !attackPrevented.getValue()) {
-						goal(new AttackPrevented(overUsage.getName().getLink()),
-								Boolean.TRUE);
-						goal(new RegularUsage(overUsage.getName().getLink()));
-					}
-				}
-			}
-		}
-
-		@Override
-		public void reviewBeliefs() {
-			synchronized (linkEvents) {
-				for (Link link : linkEvents) {
-					OverUsage overUsage = new OverUsage(link);
-					boolean isOverUsage = role.isOverUsage(link);
-
-					if (isOverUsage) {
-						PropositionalBelief<OverUsage> overUsageBelief = (PropositionalBelief<OverUsage>) getBeliefBase()
-								.getBelief(overUsage);
-						if (overUsageBelief == null
-								|| !overUsageBelief.getValue()) {
-							belief(overUsage, true);
-							belief(new RegularUsage(link), null);
-						}
-					} else {
-						belief(overUsage, null);
-					}
-				}
-				linkEvents.clear();
-			}
-		}
-	}
+		BeliefRevisionStrategy, OptionGenerationFunction, Observer {
 
 	public static final double OVER_USAGE_THRESHOLD = 0.8;
 
@@ -96,22 +50,72 @@ public class LinkMonitorCapability extends RouterAgentCapability implements
 
 	@bdi4jade.annotation.TransientBeliefSet
 	private final Set<Link> linkEvents;
-
 	@bdi4jade.annotation.Belief
-	private Belief<String, Double> overUsageThreshold = new TransientBelief<>(
-			"threshold", OVER_USAGE_THRESHOLD);
-
+	private Belief<String, Double> overUsageThreshold;
 	@bdi4jade.annotation.TransientBelief
 	private LinkMonitor role;
 
 	public LinkMonitorCapability(LinkMonitor linkMonitor) {
 		this.role = linkMonitor;
-		linkMonitor.attachObserver(this);
+		role.attachObserver(this);
+
+		setBeliefRevisionStrategy(this);
+		setOptionGenerationFunction(this);
+
 		this.linkEvents = new HashSet<>();
+		this.overUsageThreshold = new TransientBelief<>("threshold",
+				OVER_USAGE_THRESHOLD);
+	}
 
-		ReasoningStrategy strategy = new ReasoningStrategy();
-		setBeliefRevisionStrategy(strategy);
-		setOptionGenerationFunction(strategy);
+	@Override
+	public void generateGoals(GoalUpdateSet goalUpdateSet) {
+		Set<Belief<?, ?>> overUsageBeliefs = getBeliefBase().getBeliefsByType(
+				OverUsage.class);
+		for (Belief<?, ?> belief : overUsageBeliefs) {
+			PropositionalBelief<OverUsage> overUsage = (PropositionalBelief<OverUsage>) belief;
+			if (overUsage.getValue()) {
+				PropositionalBelief<AttackPrevented> attackPrevented = (PropositionalBelief<AttackPrevented>) getBeliefBase()
+						.getBelief(
+								new AttackPrevented(overUsage.getName()
+										.getLink()));
+				if (attackPrevented == null || !attackPrevented.getValue()) {
+					goalUpdateSet.generateGoal(createGoal(new AttackPrevented(
+							overUsage.getName().getLink()), Boolean.TRUE));
+					goalUpdateSet.generateGoal(createGoal(new RegularUsage(
+							overUsage.getName().getLink())));
+				}
+			}
+		}
+	}
+
+	@Override
+	public void reviewBeliefs() {
+		synchronized (linkEvents) {
+			for (Link link : linkEvents) {
+				OverUsage overUsage = new OverUsage(link);
+				boolean isOverUsage = role.isOverUsage(link);
+
+				if (isOverUsage) {
+					PropositionalBelief<OverUsage> overUsageBelief = (PropositionalBelief<OverUsage>) getBeliefBase()
+							.getBelief(overUsage);
+					if (overUsageBelief == null || !overUsageBelief.getValue()) {
+						belief(overUsage, true);
+						belief(new RegularUsage(link), null);
+					}
+				} else {
+					belief(overUsage, null);
+				}
+			}
+			linkEvents.clear();
+		}
+	}
+
+	@Override
+	public void setCapability(Capability capability) {
+		if (!this.equals(capability)) {
+			throw new IllegalArgumentException(
+					"This reasoning strategy is already associated with another capability.");
+		}
 	}
 
 	@Override
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RateLimiterCapability.java b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RateLimiterCapability.java
index 0d1a8ac..6da9871 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RateLimiterCapability.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RateLimiterCapability.java
@@ -29,6 +29,7 @@ import bdi4jade.annotation.Parameter;
 import bdi4jade.annotation.Parameter.Direction;
 import bdi4jade.belief.Belief;
 import bdi4jade.belief.PropositionalBelief;
+import bdi4jade.core.Capability;
 import bdi4jade.core.GoalUpdateSet;
 import bdi4jade.goal.BeliefGoal;
 import bdi4jade.goal.Goal;
@@ -36,7 +37,6 @@ import bdi4jade.goal.GoalTemplateFactory;
 import bdi4jade.plan.DefaultPlan;
 import bdi4jade.plan.Plan;
 import bdi4jade.plan.planbody.BeliefGoalPlanBody;
-import bdi4jade.reasoning.AbstractReasoningStrategy;
 import bdi4jade.reasoning.OptionGenerationFunction;
 import br.ufrgs.inf.bdinetr.agent.RouterAgent.RootCapability;
 import br.ufrgs.inf.bdinetr.domain.Flow;
@@ -60,7 +60,8 @@ import br.ufrgs.inf.bdinetr.domain.logic.LinkProposition.RegularUsage;
 /**
  * @author Ingrid Nunes
  */
-public class RateLimiterCapability extends RouterAgentCapability {
+public class RateLimiterCapability extends RouterAgentCapability implements
+		OptionGenerationFunction {
 
 	public class LimitFlowRatePlan extends BeliefGoalPlanBody {
 		private static final long serialVersionUID = -3493377510830902961L;
@@ -89,8 +90,6 @@ public class RateLimiterCapability extends RouterAgentCapability {
 			if (!exists) {
 				belief(new Benign(flow.getDstIp()), true);
 			}
-
-			log.info(getGoal());
 		}
 
 		@Parameter(direction = Direction.IN)
@@ -122,9 +121,9 @@ public class RateLimiterCapability extends RouterAgentCapability {
 				if (ip.equals(overUsageCause.getName().getIp())) {
 					assert overUsageCause.getValue();
 					causedByIp.add(overUsageCause.getName());
+					it.remove();
+					belief(overUsageCause.getName(), null);
 				}
-				it.remove();
-				belief(overUsageCause.getName(), null);
 			}
 
 			for (OverUsageCause overUsageCause : causedByIp) {
@@ -143,8 +142,6 @@ public class RateLimiterCapability extends RouterAgentCapability {
 					belief(new RegularUsage(overUsageCause.getLink()), true);
 				}
 			}
-
-			log.info(getGoal());
 		}
 
 		@Parameter(direction = Direction.IN)
@@ -163,7 +160,6 @@ public class RateLimiterCapability extends RouterAgentCapability {
 			role.limitLink(link, LINK_LIMIT_RATE);
 			belief(new FullyOperational(link), false);
 			belief(new AttackPrevented(link), true);
-			log.info(getGoal());
 		}
 
 		@Parameter(direction = Direction.IN)
@@ -172,29 +168,6 @@ public class RateLimiterCapability extends RouterAgentCapability {
 		}
 	}
 
-	private class ReasoningStrategy extends AbstractReasoningStrategy implements
-			OptionGenerationFunction {
-		@Override
-		public void generateGoals(GoalUpdateSet goalUpdateSet) {
-			Set<Belief<?, ?>> fullyOperationalBeliefs = getBeliefBase()
-					.getBeliefsByType(FullyOperational.class);
-			for (Belief<?, ?> belief : fullyOperationalBeliefs) {
-				PropositionalBelief<FullyOperational> fullyOperational = (PropositionalBelief<FullyOperational>) belief;
-				if (!fullyOperational.getValue()) {
-					PropositionalBelief<RegularUsage> regularUsage = (PropositionalBelief<RegularUsage>) getBeliefBase()
-							.getBelief(
-									new RegularUsage(fullyOperational.getName()
-											.getLink()));
-					if (regularUsage != null && regularUsage.getValue()) {
-						goal(new FullyOperational(fullyOperational.getName()
-								.getLink()), true);
-					}
-
-				}
-			}
-		}
-	}
-
 	public class RestoreIPRatePlan extends BeliefGoalPlanBody {
 		private static final long serialVersionUID = -3493377510830902961L;
 
@@ -208,7 +181,6 @@ public class RateLimiterCapability extends RouterAgentCapability {
 			belief(new RateLimited(ip), false);
 			belief(new Restricted(ip), false);
 			belief(new Anomalous(ip), null);
-			log.info(getGoal());
 		}
 
 		@Parameter(direction = Direction.IN)
@@ -227,7 +199,6 @@ public class RateLimiterCapability extends RouterAgentCapability {
 			role.unlimitLink(link);
 			belief(new FullyOperational(link), true);
 			belief(new AttackPrevented(link), null);
-			log.info(getGoal());
 		}
 
 		@Parameter(direction = Direction.IN)
@@ -239,80 +210,125 @@ public class RateLimiterCapability extends RouterAgentCapability {
 	public static final double FLOW_LIMIT_RATE = 0.5;
 	public static final double IP_LIMIT_RATE = 0.5;
 	public static final double LINK_LIMIT_RATE = 0.5;
-
 	private static final long serialVersionUID = -1705728861020677126L;
 
 	@bdi4jade.annotation.Plan
-	private Plan limitFlowRate = new DefaultPlan(
-			GoalTemplateFactory.hasValueForBeliefOfType(ThreatResponded.class,
-					Boolean.TRUE), LimitFlowRatePlan.class) {
-		public boolean isContextApplicable(Goal goal) {
-			BeliefGoal<ThreatResponded> bg = (BeliefGoal<ThreatResponded>) goal;
-			PropositionalBelief<Threat> threat = (PropositionalBelief<Threat>) getBeliefBase()
-					.getBelief(new Threat(bg.getBeliefName().getFlow()));
-			return (threat != null && threat.getValue());
-		};
-	};
-
+	private Plan limitFlowRate;
 	@bdi4jade.annotation.Plan
-	private Plan limitIpRate = new DefaultPlan(
-			GoalTemplateFactory.hasValueForBeliefOfType(Restricted.class,
-					Boolean.TRUE), LimitIPRatePlan.class) {
-		public boolean isContextApplicable(Goal goal) {
-			BeliefGoal<Restricted> bg = (BeliefGoal<Restricted>) goal;
-			PropositionalBelief<Anomalous> anomalous = (PropositionalBelief<Anomalous>) getBeliefBase()
-					.getBelief(new Anomalous(bg.getBeliefName().getIp()));
-			return (anomalous != null && anomalous.getValue());
-		};
-	};
-
+	private Plan limitIpRate;
 	@bdi4jade.annotation.Plan
-	private Plan limitLinkRate = new DefaultPlan(
-			GoalTemplateFactory.hasValueForBeliefOfType(AttackPrevented.class,
-					Boolean.TRUE), LimitLinkRatePlan.class) {
-		public boolean isContextApplicable(Goal goal) {
-			BeliefGoal<AttackPrevented> bg = (BeliefGoal<AttackPrevented>) goal;
-			PropositionalBelief<OverUsage> overUsage = (PropositionalBelief<OverUsage>) getBeliefBase()
-					.getBelief(new OverUsage(bg.getBeliefName().getLink()));
-			return (overUsage != null && overUsage.getValue());
-		};
-	};
-
+	private Plan limitLinkRate;
 	@bdi4jade.annotation.Plan
-	private Plan restoreIpRate = new DefaultPlan(
-			GoalTemplateFactory.hasValueForBeliefOfType(Restricted.class,
-					Boolean.FALSE), RestoreIPRatePlan.class) {
-		public boolean isContextApplicable(Goal goal) {
-			BeliefGoal<Restricted> bg = (BeliefGoal<Restricted>) goal;
-			PropositionalBelief<Benign> benign = (PropositionalBelief<Benign>) getBeliefBase()
-					.getBelief(new Benign(bg.getBeliefName().getIp()));
-			PropositionalBelief<RateLimited> rateLimited = (PropositionalBelief<RateLimited>) getBeliefBase()
-					.getBelief(new RateLimited(bg.getBeliefName().getIp()));
-			return (benign != null && benign.getValue())
-					&& (rateLimited != null && rateLimited.getValue());
-		};
-	};
-
+	private Plan restoreIpRate;
 	@bdi4jade.annotation.Plan
-	private Plan restoreLinkRate = new DefaultPlan(
-			GoalTemplateFactory.hasValueForBeliefOfType(FullyOperational.class,
-					Boolean.TRUE), RestoreLinkRate.class) {
-		public boolean isContextApplicable(Goal goal) {
-			BeliefGoal<FullyOperational> bg = (BeliefGoal<FullyOperational>) goal;
-			PropositionalBelief<RegularUsage> regularUsage = (PropositionalBelief<RegularUsage>) getBeliefBase()
-					.getBelief(new RegularUsage(bg.getBeliefName().getLink()));
-			return (regularUsage != null && regularUsage.getValue());
-		};
-	};
-
+	private Plan restoreLinkRate;
 	@bdi4jade.annotation.TransientBelief
 	private final RateLimiter role;
 
 	public RateLimiterCapability(RateLimiter rateLimiter) {
 		this.role = rateLimiter;
 
-		ReasoningStrategy strategy = new ReasoningStrategy();
-		setOptionGenerationFunction(strategy);
+		setOptionGenerationFunction(this);
+
+		limitFlowRate = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(
+						ThreatResponded.class, Boolean.TRUE),
+				LimitFlowRatePlan.class) {
+			public boolean isContextApplicable(Goal goal) {
+				BeliefGoal<ThreatResponded> bg = (BeliefGoal<ThreatResponded>) goal;
+				PropositionalBelief<Threat> threat = (PropositionalBelief<Threat>) getBeliefBase()
+						.getBelief(new Threat(bg.getBeliefName().getFlow()));
+				return (threat != null && threat.getValue());
+			};
+		};
+		limitIpRate = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(Restricted.class,
+						Boolean.TRUE), LimitIPRatePlan.class) {
+			public boolean isContextApplicable(Goal goal) {
+				BeliefGoal<Restricted> bg = (BeliefGoal<Restricted>) goal;
+				PropositionalBelief<Anomalous> anomalous = (PropositionalBelief<Anomalous>) getBeliefBase()
+						.getBelief(new Anomalous(bg.getBeliefName().getIp()));
+				return (anomalous != null && anomalous.getValue());
+			};
+		};
+		limitLinkRate = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(
+						AttackPrevented.class, Boolean.TRUE),
+				LimitLinkRatePlan.class) {
+			public boolean isContextApplicable(Goal goal) {
+				BeliefGoal<AttackPrevented> bg = (BeliefGoal<AttackPrevented>) goal;
+				PropositionalBelief<OverUsage> overUsage = (PropositionalBelief<OverUsage>) getBeliefBase()
+						.getBelief(new OverUsage(bg.getBeliefName().getLink()));
+				return (overUsage != null && overUsage.getValue());
+			};
+		};
+		restoreIpRate = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(Restricted.class,
+						Boolean.FALSE), RestoreIPRatePlan.class) {
+			public boolean isContextApplicable(Goal goal) {
+				BeliefGoal<Restricted> bg = (BeliefGoal<Restricted>) goal;
+				PropositionalBelief<Benign> benign = (PropositionalBelief<Benign>) getBeliefBase()
+						.getBelief(new Benign(bg.getBeliefName().getIp()));
+				PropositionalBelief<RateLimited> rateLimited = (PropositionalBelief<RateLimited>) getBeliefBase()
+						.getBelief(new RateLimited(bg.getBeliefName().getIp()));
+				return (benign != null && benign.getValue())
+						&& (rateLimited != null && rateLimited.getValue());
+			};
+		};
+		restoreLinkRate = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(
+						FullyOperational.class, Boolean.TRUE),
+				RestoreLinkRate.class) {
+			public boolean isContextApplicable(Goal goal) {
+				BeliefGoal<FullyOperational> bg = (BeliefGoal<FullyOperational>) goal;
+				PropositionalBelief<RegularUsage> regularUsage = (PropositionalBelief<RegularUsage>) getBeliefBase()
+						.getBelief(
+								new RegularUsage(bg.getBeliefName().getLink()));
+				return (regularUsage != null && regularUsage.getValue());
+			};
+		};
+	}
+
+	@Override
+	public void generateGoals(GoalUpdateSet goalUpdateSet) {
+		Set<Belief<?, ?>> fullyOperationalBeliefs = getBeliefBase()
+				.getBeliefsByType(FullyOperational.class);
+		for (Belief<?, ?> belief : fullyOperationalBeliefs) {
+			PropositionalBelief<FullyOperational> fullyOperational = (PropositionalBelief<FullyOperational>) belief;
+			if (!fullyOperational.getValue()) {
+				PropositionalBelief<RegularUsage> regularUsage = (PropositionalBelief<RegularUsage>) getBeliefBase()
+						.getBelief(
+								new RegularUsage(fullyOperational.getName()
+										.getLink()));
+				if (regularUsage != null && regularUsage.getValue()) {
+					goalUpdateSet.generateGoal(createGoal(new FullyOperational(
+							fullyOperational.getName().getLink()), true));
+				}
+
+			}
+		}
+
+		Set<Belief<?, ?>> restrictedBeliefs = getBeliefBase().getBeliefsByType(
+				Restricted.class);
+		for (Belief<?, ?> belief : restrictedBeliefs) {
+			PropositionalBelief<Restricted> restricted = (PropositionalBelief<Restricted>) belief;
+			if (restricted.getValue()) {
+				PropositionalBelief<Benign> benign = (PropositionalBelief<Benign>) getBeliefBase()
+						.getBelief(new Benign(restricted.getName().getIp()));
+				if (benign != null && benign.getValue()) {
+					goalUpdateSet.generateGoal(createGoal(new Restricted(
+							restricted.getName().getIp()), false));
+				}
+			}
+		}
+	}
+
+	@Override
+	public void setCapability(Capability capability) {
+		if (!this.equals(capability)) {
+			throw new IllegalArgumentException(
+					"This reasoning strategy is already associated with another capability.");
+		}
 	}
 
 }
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RequestBeliefGoalPlanBody.java b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RequestBeliefGoalPlanBody.java
new file mode 100644
index 0000000..12eeb3c
--- /dev/null
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RequestBeliefGoalPlanBody.java
@@ -0,0 +1,87 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+package br.ufrgs.inf.bdinetr.agent;
+
+import jade.core.AID;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.BeliefGoalPlanBody;
+
+/**
+ * @author Ingrid Nunes
+ */
+public class RequestBeliefGoalPlanBody extends BeliefGoalPlanBody {
+
+	private enum State {
+		Resquesting, ReceivingResponses, Selecting, AchievingGoal, Ended;
+	}
+
+	private static final long serialVersionUID = -1833810388789537049L;
+
+	private MessageTemplate mt;
+	private State state;
+
+	@Override
+	protected void execute() {
+		switch (state) {
+		case Resquesting:
+
+			ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
+			msg.setContent("");
+			msg.addReceiver(new AID("", false));
+			msg.setConversationId("cin" + System.currentTimeMillis());
+			msg.setReplyWith("inform" + System.currentTimeMillis());
+			myAgent.send(msg);
+			this.mt = MessageTemplate.and(MessageTemplate
+					.MatchConversationId(msg.getConversationId()),
+					MessageTemplate.MatchInReplyTo(msg.getReplyWith()));
+			break;
+		case ReceivingResponses:
+			ACLMessage reply = myAgent.receive(mt);
+			if (reply != null) {
+				log.info("Pong received from " + reply.getSender().getName()
+						+ "!");
+				log.info("Content: " + reply.getContent());
+				
+			} else {
+				block();
+			}
+			break;
+		case Selecting:
+
+			break;
+		case AchievingGoal:
+
+			break;
+		case Ended:
+
+			break;
+		}
+	}
+
+	@Override
+	public void onStart() {
+		this.state = State.Resquesting;
+	}
+
+}
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RespondBeliefGoalPlanBody.java b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RespondBeliefGoalPlanBody.java
new file mode 100644
index 0000000..2e43774
--- /dev/null
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RespondBeliefGoalPlanBody.java
@@ -0,0 +1,75 @@
+//----------------------------------------------------------------------------
+// Copyright (C) 2011  Ingrid Nunes
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+// 
+// To contact the authors:
+// http://inf.ufrgs.br/prosoft/bdi4jade/
+//
+//----------------------------------------------------------------------------
+package br.ufrgs.inf.bdinetr.agent;
+
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+import bdi4jade.annotation.Parameter;
+import bdi4jade.annotation.Parameter.Direction;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+
+/**
+ * @author Ingrid Nunes
+ */
+public class RespondBeliefGoalPlanBody extends AbstractPlanBody {
+
+	private enum State {
+		SendingResponse, ReceivingReply, AchievingBeliefGoal, Ended;
+	}
+
+	private static final long serialVersionUID = -4231465068344668721L;
+
+	private ACLMessage beliefGoalMsg;
+	private MessageTemplate mt;
+	private State state;
+
+	@Override
+	public void action() {
+		switch (state) {
+		case SendingResponse:
+			ACLMessage reply = beliefGoalMsg.createReply();
+			reply.setContent("");
+			this.myAgent.send(reply);
+			break;
+		case ReceivingReply:
+
+			break;
+		case AchievingBeliefGoal:
+
+			break;
+		case Ended:
+
+			break;
+		}
+	}
+
+	@Override
+	public void onStart() {
+		this.state = State.SendingResponse;
+	}
+
+	@Parameter(direction = Direction.IN)
+	public void setMessage(ACLMessage beliefGoalMsg) {
+		this.beliefGoalMsg = beliefGoalMsg;
+	}
+
+}
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RouterAgent.java b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RouterAgent.java
index 42ce3d5..c352d25 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RouterAgent.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RouterAgent.java
@@ -21,10 +21,24 @@
 //----------------------------------------------------------------------------
 package br.ufrgs.inf.bdinetr.agent;
 
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+import jade.lang.acl.MessageTemplate.MatchExpression;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
 import bdi4jade.belief.Belief;
 import bdi4jade.belief.TransientBelief;
+import bdi4jade.core.BDIAgent;
 import bdi4jade.core.Capability;
 import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.goal.BeliefGoal;
+import bdi4jade.goal.Goal;
+import bdi4jade.plan.DefaultPlan;
+import bdi4jade.plan.Plan;
+import bdi4jade.reasoning.AgentPlanSelectionStrategy;
 import br.ufrgs.inf.bdinetr.domain.AnomalyDetection;
 import br.ufrgs.inf.bdinetr.domain.Classifier;
 import br.ufrgs.inf.bdinetr.domain.LinkMonitor;
@@ -35,7 +49,8 @@ import br.ufrgs.inf.bdinetr.domain.RateLimiter;
 /**
  * @author Ingrid Nunes
  */
-public class RouterAgent extends SingleCapabilityAgent {
+public class RouterAgent extends SingleCapabilityAgent implements
+		AgentPlanSelectionStrategy {
 
 	public static class RootCapability extends Capability {
 
@@ -43,12 +58,32 @@ public class RouterAgent extends SingleCapabilityAgent {
 
 		private static final long serialVersionUID = -2156730094556459899L;
 
+		@bdi4jade.annotation.Plan
+		private final Plan requestBeliefGoalPlan;
+		@bdi4jade.annotation.Plan
+		private final Plan respondBeliefGoalPlan;
 		@bdi4jade.annotation.Belief
-		private Belief<String, PReSETRouter> router = new TransientBelief<>(
-				ROUTER_BELIEF);
+		private final Belief<String, PReSETRouter> router;
 
 		public RootCapability(PReSETRouter router) {
-			this.router.setValue(router);
+			this.router = new TransientBelief<>(ROUTER_BELIEF, router);
+			this.requestBeliefGoalPlan = new DefaultPlan(BeliefGoal.class,
+					RequestBeliefGoalPlanBody.class);
+			this.respondBeliefGoalPlan = new DefaultPlan(new MessageTemplate(
+					new MatchExpression() {
+						private static final long serialVersionUID = -3581014512390059387L;
+
+						@Override
+						public boolean match(ACLMessage msg) {
+							try {
+								return (msg.getContentObject() != null && msg
+										.getContentObject() instanceof BeliefGoal<?>);
+							} catch (Exception exc) {
+								log.error(exc);
+								return false;
+							}
+						}
+					}), RespondBeliefGoalPlanBody.class);
 		}
 
 	}
@@ -61,19 +96,53 @@ public class RouterAgent extends SingleCapabilityAgent {
 			this.getCapability().addPartCapability(
 					new LinkMonitorCapability((LinkMonitor) router
 							.getRole(RoleType.LINK_MONITOR)));
-		} else if (router.hasRole(RoleType.ANOMALY_DETECTION)) {
+		}
+		if (router.hasRole(RoleType.ANOMALY_DETECTION)) {
 			this.getCapability().addPartCapability(
 					new AnomalyDetectionCapability((AnomalyDetection) router
 							.getRole(RoleType.ANOMALY_DETECTION)));
-		} else if (router.hasRole(RoleType.RATE_LIMITER)) {
+		}
+		if (router.hasRole(RoleType.RATE_LIMITER)) {
 			this.getCapability().addPartCapability(
 					new RateLimiterCapability((RateLimiter) router
 							.getRole(RoleType.RATE_LIMITER)));
-		} else if (router.hasRole(RoleType.CLASSIFIER)) {
+		}
+		if (router.hasRole(RoleType.CLASSIFIER)) {
 			this.getCapability().addPartCapability(
 					new ClassifierCapability((Classifier) router
 							.getRole(RoleType.CLASSIFIER)));
 		}
 	}
 
+	@Override
+	public Plan selectPlan(Goal goal, Map<Capability, Set<Plan>> capabilityPlans) {
+		Set<Plan> preselectedPlans = new HashSet<>();
+		for (Capability capability : capabilityPlans.keySet()) {
+			if (!getCapability().equals(capability)) {
+				Plan preselectedPlan = capability.getPlanSelectionStrategy()
+						.selectPlan(goal, capabilityPlans.get(capability));
+				if (preselectedPlan != null) {
+					preselectedPlans.add(preselectedPlan);
+				}
+			}
+		}
+
+		if (preselectedPlans.isEmpty()) {
+			Set<Plan> candidatePlans = capabilityPlans.get(getCapability());
+			return (candidatePlans == null) ? null : getCapability()
+					.getPlanSelectionStrategy()
+					.selectPlan(goal, candidatePlans);
+		} else {
+			return preselectedPlans.iterator().next();
+		}
+	}
+
+	@Override
+	public void setAgent(BDIAgent agent) {
+		if (!this.equals(agent)) {
+			throw new IllegalArgumentException(
+					"This reasoning strategy is already associated with another agent.");
+		}
+	}
+
 }
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RouterAgentCapability.java b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RouterAgentCapability.java
index 1e98cc1..c265359 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RouterAgentCapability.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/agent/RouterAgentCapability.java
@@ -24,6 +24,7 @@ package br.ufrgs.inf.bdinetr.agent;
 import bdi4jade.belief.TransientPropositionalBelief;
 import bdi4jade.core.Capability;
 import bdi4jade.goal.BeliefPresentGoal;
+import bdi4jade.goal.Goal;
 import bdi4jade.goal.PropositionalBeliefValueGoal;
 
 /**
@@ -46,15 +47,22 @@ public class RouterAgentCapability extends Capability {
 		}
 	}
 
-	protected void goal(Object proposition) {
-		getMyAgent().addGoal(this, new BeliefPresentGoal(proposition));
+	protected Goal createGoal(Object proposition) {
 		log.debug("goal(?" + proposition + "))");
+		return new BeliefPresentGoal(proposition);
 	}
 
-	protected void goal(Object proposition, Boolean value) {
-		getMyAgent().addGoal(this,
-				new PropositionalBeliefValueGoal(proposition, value));
+	protected Goal createGoal(Object proposition, Boolean value) {
 		log.debug("goal(" + (value ? "" : "not ") + proposition + "))");
+		return new PropositionalBeliefValueGoal(proposition, value);
+	}
+
+	protected void goal(Object proposition) {
+		getMyAgent().addGoal(this, createGoal(proposition));
+	}
+
+	protected void goal(Object proposition, Boolean value) {
+		getMyAgent().addGoal(this, createGoal(proposition, value));
 	}
 
 }
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/BDINetRApp.java b/network-resilience/src/br/ufrgs/inf/bdinetr/BDINetRApp.java
index 45eb143..ab1a7fd 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/BDINetRApp.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/BDINetRApp.java
@@ -30,8 +30,10 @@ import jade.wrapper.PlatformController;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -39,6 +41,8 @@ import org.apache.log4j.PropertyConfigurator;
 
 import br.ufrgs.inf.bdinetr.agent.RouterAgent;
 import br.ufrgs.inf.bdinetr.domain.Ip;
+import br.ufrgs.inf.bdinetr.domain.Link;
+import br.ufrgs.inf.bdinetr.domain.PReSETRole.RoleType;
 import br.ufrgs.inf.bdinetr.domain.PReSETRouter;
 
 /**
@@ -47,20 +51,40 @@ import br.ufrgs.inf.bdinetr.domain.PReSETRouter;
 public class BDINetRApp {
 
 	private static final Map<Ip, Agent> AGENTS;
+	private static final Network NETWORK;
 
 	static {
 		PropertyConfigurator.configure(BDINetRApp.class
 				.getResource("log4j.properties"));
 
+		Set<PReSETRouter> routers = new HashSet<>();
+		routers.add(new PReSETRouter(new Ip("Router"), RoleType.RATE_LIMITER
+				.getId()
+				| RoleType.CLASSIFIER.getId()
+				| RoleType.ANOMALY_DETECTION.getId()
+				| RoleType.LINK_MONITOR.getId()));
+
+		Link affectedLink = new Link("AFFECTED_LINK");
+
+		Set<Link> links = new HashSet<>();
+		links.add(affectedLink);
+		links.add(new Link("LINK_01"));
+		links.add(new Link("LINK_02"));
+
+		Set<Link> affectedLinks = new HashSet<>();
+		affectedLinks.add(affectedLink);
+
+		NETWORK = new Network(routers, links, affectedLinks);
+
 		AGENTS = new HashMap<>();
-		for (PReSETRouter router : Network.NETWORK.getRouters()) {
+		for (PReSETRouter router : NETWORK.getRouters()) {
 			AGENTS.put(router.getIp(), new RouterAgent(router));
 		}
 	}
 
 	public static void main(String[] args) {
 		new BDINetRApp();
-		Network.NETWORK.run();
+		NETWORK.run();
 	}
 
 	private ProfileImpl bootProfile;
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/domain/logic/IpPreposition.java b/network-resilience/src/br/ufrgs/inf/bdinetr/domain/logic/IpPreposition.java
index 28b5de2..bd5b20c 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/domain/logic/IpPreposition.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/domain/logic/IpPreposition.java
@@ -72,6 +72,14 @@ public class IpPreposition {
 			return result;
 		}
 
+		@Override
+		public String toString() {
+			StringBuffer sb = new StringBuffer();
+			sb.append(this.getClass().getSimpleName());
+			sb.append("(").append(ip).append(",").append(link).append(")");
+			return sb.toString();
+		}
+
 	}
 
 	public static class RateLimited extends IpPreposition {
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/domain/PReSETRouter.java b/network-resilience/src/br/ufrgs/inf/bdinetr/domain/PReSETRouter.java
index 80d2ffe..8e989af 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/domain/PReSETRouter.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/domain/PReSETRouter.java
@@ -39,12 +39,15 @@ public class PReSETRouter {
 		this.roles = new HashMap<>();
 		if (RoleType.LINK_MONITOR.isPresent(roles)) {
 			this.roles.put(RoleType.LINK_MONITOR, new LinkMonitor(this));
-		} else if (RoleType.ANOMALY_DETECTION.isPresent(roles)) {
+		}
+		if (RoleType.ANOMALY_DETECTION.isPresent(roles)) {
 			this.roles.put(RoleType.ANOMALY_DETECTION, new AnomalyDetection(
 					this));
-		} else if (RoleType.RATE_LIMITER.isPresent(roles)) {
+		}
+		if (RoleType.RATE_LIMITER.isPresent(roles)) {
 			this.roles.put(RoleType.RATE_LIMITER, new RateLimiter(this));
-		} else if (RoleType.CLASSIFIER.isPresent(roles)) {
+		}
+		if (RoleType.CLASSIFIER.isPresent(roles)) {
 			this.roles.put(RoleType.CLASSIFIER, new Classifier(this));
 		}
 	}
diff --git a/network-resilience/src/br/ufrgs/inf/bdinetr/Network.java b/network-resilience/src/br/ufrgs/inf/bdinetr/Network.java
index 32dbbe2..f6f3eba 100644
--- a/network-resilience/src/br/ufrgs/inf/bdinetr/Network.java
+++ b/network-resilience/src/br/ufrgs/inf/bdinetr/Network.java
@@ -21,14 +21,12 @@
 //----------------------------------------------------------------------------
 package br.ufrgs.inf.bdinetr;
 
-import java.util.HashSet;
 import java.util.Set;
-import java.util.Timer;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import br.ufrgs.inf.bdinetr.domain.Ip;
+import bdi4jade.examples.BDI4JADEExamplesPanel;
 import br.ufrgs.inf.bdinetr.domain.Link;
 import br.ufrgs.inf.bdinetr.domain.LinkMonitor;
 import br.ufrgs.inf.bdinetr.domain.Observer;
@@ -42,34 +40,19 @@ import br.ufrgs.inf.bdinetr.domain.RateLimiter.LimitLinkEvent;
  */
 public class Network implements Observer {
 
-	public static final Link AFFECTED_LINK;
-	public static final Network NETWORK;
-
-	static {
-		NETWORK = new Network();
-		NETWORK.addRouter(new PReSETRouter(new Ip("Router"),
-				RoleType.RATE_LIMITER.getId() | RoleType.CLASSIFIER.getId()
-						| RoleType.ANOMALY_DETECTION.getId()
-						| RoleType.LINK_MONITOR.getId()));
-
-		AFFECTED_LINK = new Link("AFFECTED_LINK");
-		NETWORK.addLink(AFFECTED_LINK);
-		NETWORK.addLink(new Link("LINK_01"));
-		NETWORK.addLink(new Link("LINK_02"));
-	}
-
+	private final Set<Link> affectedLinks;
 	private final Set<Link> links;
 	private final Log log;
-	private final Set<PReSETRouter> router;
-	private Timer timer;
+	private final Set<PReSETRouter> routers;
 
-	public Network() {
+	public Network(Set<PReSETRouter> routers, Set<Link> links,
+			Set<Link> affectedLinks) {
 		this.log = LogFactory.getLog(this.getClass());
-		this.router = new HashSet<>();
-		this.links = new HashSet<>();
-		this.timer = new Timer();
+		this.routers = routers;
+		this.links = links;
+		this.affectedLinks = affectedLinks;
 
-		for (PReSETRouter router : NETWORK.getRouters()) {
+		for (PReSETRouter router : routers) {
 			if (router.hasRole(RoleType.RATE_LIMITER)) {
 				((RateLimiter) router.getRole(RoleType.RATE_LIMITER))
 						.attachObserver(this);
@@ -82,7 +65,7 @@ public class Network implements Observer {
 	}
 
 	public void addRouter(PReSETRouter router) {
-		this.router.add(router);
+		this.routers.add(router);
 	}
 
 	public Set<Link> getLinks() {
@@ -90,7 +73,7 @@ public class Network implements Observer {
 	}
 
 	public Set<PReSETRouter> getRouters() {
-		return router;
+		return routers;
 	}
 
 	/**
@@ -99,11 +82,13 @@ public class Network implements Observer {
 	 */
 	public void run() {
 		log.info("Updating link usage");
-		for (PReSETRouter router : NETWORK.getRouters()) {
-			if (router.hasRole(RoleType.LINK_MONITOR)) {
-				LinkMonitor lm = (LinkMonitor) router
-						.getRole(RoleType.LINK_MONITOR);
-				lm.setOverUsage(AFFECTED_LINK, true);
+		for (Link link : affectedLinks) {
+			for (PReSETRouter router : routers) {
+				if (router.hasRole(RoleType.LINK_MONITOR)) {
+					LinkMonitor lm = (LinkMonitor) router
+							.getRole(RoleType.LINK_MONITOR);
+					lm.setOverUsage(link, true);
+				}
 			}
 		}
 	}
@@ -112,7 +97,7 @@ public class Network implements Observer {
 	public void update(Object o, Object arg) {
 		if (arg instanceof LimitLinkEvent) {
 			LimitLinkEvent event = (LimitLinkEvent) arg;
-			for (PReSETRouter router : NETWORK.getRouters()) {
+			for (PReSETRouter router : routers) {
 				if (router.hasRole(RoleType.LINK_MONITOR)) {
 					LinkMonitor lm = (LinkMonitor) router
 							.getRole(RoleType.LINK_MONITOR);