package org.opendaylight.affinity.analytics.internal;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.controller.sal.match.MatchField;
+import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.controller.sal.reader.FlowOnNode;
+import org.opendaylight.controller.sal.utils.IPProtocols;
public class HostStats {
- private long byteCount;
- private double duration;
+ private Map<Byte, Long> byteCounts;
+ private Map<Byte, Double> durations;
public HostStats() {
- this.byteCount = 0;
- this.duration = 0;
+ this.byteCounts = new HashMap<Byte, Long>();
+ this.durations = new HashMap<Byte, Double>();
}
public long getByteCount() {
- return this.byteCount;
- }
-
- public void setByteCount(long byteCount) {
- this.byteCount = byteCount;
+ long totalByteCount = 0;
+ for (Byte protocol : this.byteCounts.keySet())
+ totalByteCount += this.byteCounts.get(protocol);
+ return totalByteCount;
}
public double getDuration() {
- return this.duration;
- }
-
- public void setDuration(double duration) {
- this.duration = duration;
+ return Collections.max(this.durations.values());
}
public void setStatsFromFlow(FlowOnNode flow) {
+ MatchField protocolField = flow.getFlow().getMatch().getField(MatchType.NW_PROTO);
+ Byte protocolNumber;
+ if (protocolField == null)
+ protocolNumber = IPProtocols.ANY.byteValue();
+ else
+ protocolNumber = (Byte) protocolField.getValue();
+
// Prevent stats from getting overwritten by zero-byte flows.
- // TODO: Figure out why this happens
- if (flow.getByteCount() > this.byteCount) {
- this.byteCount = flow.getByteCount();
+ Long currentByteCount = this.byteCounts.get(protocolNumber);
+ Long thisByteCount = flow.getByteCount();
+ if (thisByteCount > 0 && (currentByteCount == null || currentByteCount <= thisByteCount)) {
+ this.byteCounts.put(protocolNumber, thisByteCount);
+ this.durations.put(protocolNumber, flow.getDurationSeconds() + .000000001 * flow.getDurationNanoseconds());
}
- this.duration = flow.getDurationSeconds() + .000000001 * flow.getDurationNanoseconds();
}
public double getBitRate() {
- return (this.byteCount * 8)/(this.duration);
+ return (getByteCount() * 8)/getDuration();
}
}
*/
package org.opendaylight.affinity.l2agent;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.List;
+import java.util.Arrays;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.lang.String;
-import java.util.Map;
import java.util.HashMap;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.opendaylight.controller.sal.action.Action;
import org.opendaylight.controller.sal.action.Output;
-import org.opendaylight.controller.sal.action.Flood;
import org.opendaylight.controller.sal.core.ConstructionException;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.controller.sal.match.MatchField;
-import org.opendaylight.controller.sal.packet.ARP;
import org.opendaylight.controller.sal.packet.BitBufferHelper;
import org.opendaylight.controller.sal.packet.Ethernet;
import org.opendaylight.controller.sal.packet.IDataPacketService;
import org.opendaylight.controller.sal.packet.PacketResult;
import org.opendaylight.controller.sal.packet.RawPacket;
import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.sal.utils.NetUtils;
import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.Subnet;
public class L2Agent implements IListenDataPacket, IfL2Agent {
- private static final Logger logger = LoggerFactory
- .getLogger(L2Agent.class);
+ private static final Logger logger = LoggerFactory.getLogger(L2Agent.class);
private ISwitchManager switchManager = null;
private IFlowProgrammerService programmer = null;
private IDataPacketService dataPacketService = null;
private Map<Node, Map<Long, NodeConnector>> mac_to_ports = new HashMap<Node, Map<Long, NodeConnector>>();
- private String function = "switch";
void setDataPacketService(IDataPacketService s) {
this.dataPacketService = s;
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
*/
void init() {
logger.info("Initialized");
* Function called by the dependency manager when at least one
* dependency become unsatisfied or when the component is shutting
* down because for example bundle is being stopped.
- *
*/
void destroy() {
}
* Function called by dependency manager after "init ()" is called
* and after the services provided by the class are registered in
* the service registry
- *
*/
void start() {
logger.info("Started");
* Function called by the dependency manager before the services
* exported by the component are unregistered, this will be
* followed by a "destroy ()" calls
- *
*/
void stop() {
logger.info("Stopped");
NodeConnector incoming_connector = inPkt.getIncomingNodeConnector();
Node incoming_node = incoming_connector.getNode();
- Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
- if (formattedPak instanceof Ethernet) {
- byte[] srcMAC = ((Ethernet)formattedPak).getSourceMACAddress();
- byte[] dstMAC = ((Ethernet)formattedPak).getDestinationMACAddress();
-
- long srcMAC_val = BitBufferHelper.toNumber(srcMAC);
- long dstMAC_val = BitBufferHelper.toNumber(dstMAC);
- }
-
- Set<NodeConnector> nodeConnectors =
- this.switchManager.getUpNodeConnectors(incoming_node);
+ Set<NodeConnector> nodeConnectors = this.switchManager.getUpNodeConnectors(incoming_node);
for (NodeConnector p : nodeConnectors) {
if (!p.equals(incoming_connector)) {
RawPacket destPkt = new RawPacket(inPkt);
destPkt.setOutgoingNodeConnector(p);
this.dataPacketService.transmitDataPacket(destPkt);
- } catch (ConstructionException e2) {
+ } catch (ConstructionException e) {
continue;
}
}
}
}
+ private void installFlow(Match match, List<Action> actions, Node incoming_node, short priority) {
+ Flow f = new Flow(match, actions);
+ f.setPriority(priority);
+
+ // Modify the flow on the network node
+ Status status = programmer.addFlow(incoming_node, f);
+ if (!status.isSuccess()) {
+ logger.warn("SDN Plugin failed to program the flow: {}. The failure is: {}",
+ f, status.getDescription());
+ return;
+ }
+ logger.info("Installed flow {} in node {}", f, incoming_node);
+ }
+
@Override
public PacketResult receiveDataPacket(RawPacket inPkt) {
if (inPkt == null) {
return PacketResult.IGNORED;
}
- logger.trace("Received a frame of size: {}",
- inPkt.getPacketData().length);
+ logger.trace("Received a frame of size: {}", inPkt.getPacketData().length);
Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
NodeConnector incoming_connector = inPkt.getIncomingNodeConnector();
byte[] srcMAC = ((Ethernet)formattedPak).getSourceMACAddress();
byte[] dstMAC = ((Ethernet)formattedPak).getDestinationMACAddress();
- // Hub implementation
- if (function.equals("hub")) {
- floodPacket(inPkt);
- return PacketResult.CONSUME;
- }
-
- // Switch
- else {
- long srcMAC_val = BitBufferHelper.toNumber(srcMAC);
- long dstMAC_val = BitBufferHelper.toNumber(dstMAC);
-
- Match match = new Match();
- match.setField( new MatchField(MatchType.IN_PORT, incoming_connector) );
- match.setField( new MatchField(MatchType.DL_DST, dstMAC.clone()) );
-
- // Set up the mapping: switch -> src MAC address -> incoming port
- if (this.mac_to_ports.get(incoming_node) == null) {
- this.mac_to_ports.put(incoming_node, new HashMap<Long, NodeConnector>());
- logger.info("Added new node = {} to mac_to_ports", incoming_node);
- }
-
- // Only replace if we don't know the mapping. This
- // saves us from over-writing correct mappings with
- // incorrect ones we get during flooding.
- //
- // TODO: this should never happen..
- if (this.mac_to_ports.get(incoming_node).get(srcMAC_val) == null) {
- this.mac_to_ports.get(incoming_node).put(srcMAC_val, incoming_connector);
- logger.info("Added new learned MAC = {} on incoming connector = {} to mac_to_ports", srcMAC_val, incoming_connector);
- }
-
- NodeConnector dst_connector = this.mac_to_ports.get(incoming_node).get(dstMAC_val);
-
- // Do I know the destination MAC?
- if (dst_connector != null) {
-
- List<Action> actions = new ArrayList<Action>();
- actions.add(new Output(dst_connector));
+ long srcMAC_val = BitBufferHelper.toNumber(srcMAC);
+ long dstMAC_val = BitBufferHelper.toNumber(dstMAC);
- Flow f = new Flow(match, actions);
+ // Set up the mapping: switch -> src MAC address -> incoming port
+ if (this.mac_to_ports.get(incoming_node) == null) {
+ this.mac_to_ports.put(incoming_node, new HashMap<Long, NodeConnector>());
+ logger.info("Added new node = {} to mac_to_ports", incoming_node);
+ }
- // Modify the flow on the network node
- Status status = programmer.addFlow(incoming_node, f);
- if (!status.isSuccess()) {
- logger.warn(
- "SDN Plugin failed to program the flow: {}. The failure is: {}",
- f, status.getDescription());
- return PacketResult.IGNORED;
- }
- logger.info("Installed flow {} in node {}", f, incoming_node);
+ // Only replace if we don't know the mapping. This
+ // saves us from over-writing correct mappings with
+ // incorrect ones we get during flooding.
+ //
+ // TODO: this should never happen..
+ if (this.mac_to_ports.get(incoming_node).get(srcMAC_val) == null) {
+ this.mac_to_ports.get(incoming_node).put(srcMAC_val, incoming_connector);
+ logger.info("Added new learned MAC = {} on incoming connector = {} to mac_to_ports", srcMAC_val, incoming_connector);
+ }
- // TODO: Testing. What do the flows on this node look like now?
- // new FlowStatisticsConverter(flows).getFlowOnNodeList(node)
- }
- else {
- floodPacket(inPkt);
+ NodeConnector dst_connector = this.mac_to_ports.get(incoming_node).get(dstMAC_val);
+
+ // Do I know the destination MAC?
+ if (dst_connector != null) {
+
+ List<Action> actions = new ArrayList<Action>();
+ actions.add(new Output(dst_connector));
+
+ // Install a high(er)-priority flow for each of the three protocols we care about
+ List<Byte> protocolList = Arrays.asList(IPProtocols.ICMP.byteValue(), IPProtocols.TCP.byteValue(), IPProtocols.UDP.byteValue());
+ for (byte protocol : protocolList) {
+ Match match = new Match();
+ match.setField(new MatchField(MatchType.IN_PORT, incoming_connector));
+ match.setField(new MatchField(MatchType.DL_DST, dstMAC.clone()));
+ // To get the actual protocol used in this packet, if it's an IPv4 packet:
+ // ((IPv4) formattedPak.getPayload()).getProtocol();
+ match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));
+ match.setField(new MatchField(MatchType.NW_PROTO, protocol));
+ installFlow(match, actions, incoming_node, (short) 2);
}
+
+ // Install a low-priority flow to catch everything else
+ Match match = new Match();
+ match.setField(new MatchField(MatchType.IN_PORT, incoming_connector));
+ match.setField(new MatchField(MatchType.DL_DST, dstMAC.clone()));
+ installFlow(match, actions, incoming_node, (short) 1);
+ }
+ else {
+ floodPacket(inPkt);
}
}
return PacketResult.IGNORED;