Ayaka Koshibe

added simple storage to SimpleFlowRuleManager

Change-Id: I7f9117c534673b00f2822cf90bd63d52b95d2704
package org.onlab.onos.net.flow;
import org.onlab.onos.net.DeviceId;
public class DefaultFlowEntry extends DefaultFlowRule implements FlowEntry {
private final int priority;
private final long created;
private final FlowId id;
public DefaultFlowEntry(DefaultFlowEntry entry) {
super(entry.deviceId(), entry.selector(), entry.treatment());
this.priority = entry.priority;
this.created = entry.created;
this.id = entry.id;
}
public DefaultFlowEntry(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, int priority) {
super(deviceId, selector, treatment);
this.priority = priority;
this.created = System.currentTimeMillis();
this.id = FlowId.valueOf(this.hashCode());
}
@Override
public FlowId id() {
return null;
}
@Override
public int priority() {
return priority;
}
@Override
public long lifeMillis() {
return (created - System.currentTimeMillis());
}
@Override
public long idleMillis() {
return 0;
}
@Override
public long packets() {
return 0;
}
@Override
public long bytes() {
return 0;
}
@Override
/*
* currently uses the parts that definitely have a defined hashcode...
*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
final int prime = 31;
int result = prime * this.deviceId().hashCode();
result = prime * result + Long.valueOf(this.created).hashCode();
return result;
}
@Override
/*
* The priority and statistics can change on a given treatment and selector
*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (obj instanceof DefaultFlowEntry) {
DefaultFlowEntry that = (DefaultFlowEntry) obj;
if (!this.id.equals(that.id())) {
return false;
}
return super.equals(obj);
}
return false;
}
}
......@@ -35,4 +35,37 @@ public class DefaultFlowRule implements FlowRule {
return treatment;
}
@Override
public int hashCode() {
final int prime = 31;
int result = prime * this.deviceId().hashCode();
result = prime * result + selector.hashCode();
result = prime * result + treatment.hashCode();
return result;
}
@Override
/*
* The priority and statistics can change on a given treatment and selector
*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (obj instanceof FlowRule) {
DefaultFlowRule that = (DefaultFlowRule) obj;
if (!this.deviceId().equals(that.deviceId())) {
return false;
}
if (!this.treatment().equals(that.treatment())) {
return false;
}
if (!this.selector().equals(that.selector())) {
return false;
}
}
return true;
}
}
......
......@@ -5,7 +5,11 @@ package org.onlab.onos.net.flow;
*/
public interface FlowEntry extends FlowRule {
/**
* Returns the ID of this flow.
*
* @return the flow ID
*/
FlowId id();
/**
......
package org.onlab.onos.net.flow;
import java.util.List;
import org.onlab.onos.net.DeviceId;
/**
......@@ -30,7 +32,7 @@ public interface FlowRuleService {
* throws SomeKindOfException that indicates which ones were applied and
* which ones failed
*/
void applyFlowRules(FlowRule... flowRules);
List<FlowEntry> applyFlowRules(FlowRule... flowRules);
/**
* Removes the specified flow rules from their respective devices. If the
......
......@@ -2,6 +2,9 @@ package org.onlab.onos.net.trivial.flow.impl;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.ArrayList;
import java.util.List;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -25,17 +28,22 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
@Component(immediate = true)
@Service
public class SimpleFlowRuleManager
extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
implements FlowRuleService, FlowRuleProviderRegistry {
public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
private final Logger log = getLogger(getClass());
private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
listenerRegistry = new AbstractListenerRegistry<>();
private final SimpleFlowRuleStore store = new SimpleFlowRuleStore();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private EventDeliveryService eventDispatcher;
......@@ -56,30 +64,31 @@ implements FlowRuleService, FlowRuleProviderRegistry {
@Override
public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
//TODO: store rules somewhere and return them here
return null;
return store.getFlowEntries(deviceId);
}
@Override
public void applyFlowRules(FlowRule... flowRules) {
public List<FlowEntry> applyFlowRules(FlowRule... flowRules) {
List<FlowEntry> entries = new ArrayList<FlowEntry>();
for (int i = 0; i < flowRules.length; i++) {
FlowRule f = flowRules[0];
FlowRule f = flowRules[i];
final Device device = deviceService.getDevice(f.deviceId());
final FlowRuleProvider frp = getProvider(device.providerId());
//TODO: store rules somewhere
entries.add(store.storeFlowRule(f));
frp.applyFlowRule(f);
}
return entries;
}
@Override
public void removeFlowRules(FlowRule... flowRules) {
for (int i = 0; i < flowRules.length; i++) {
FlowRule f = flowRules[0];
FlowRule f = flowRules[i];
final Device device = deviceService.getDevice(f.deviceId());
final FlowRuleProvider frp = getProvider(device.providerId());
//TODO: remove stored rules from wherever they are
store.removeFlowRule(f);
frp.removeFlowRule(f);
}
......@@ -111,22 +120,44 @@ implements FlowRuleService, FlowRuleProviderRegistry {
@Override
public void flowRemoved(FlowRule flowRule) {
// TODO Auto-generated method stub
checkNotNull(flowRule, FLOW_RULE_NULL);
checkValidity();
FlowRuleEvent event = store.removeFlowRule(flowRule);
if (event != null) {
log.debug("Flow {} removed", flowRule);
post(event);
}
}
@Override
public void flowMissing(FlowRule flowRule) {
checkNotNull(flowRule, FLOW_RULE_NULL);
checkValidity();
// TODO Auto-generated method stub
}
@Override
public void flowAdded(FlowRule flowRule) {
// TODO Auto-generated method stub
checkNotNull(flowRule, FLOW_RULE_NULL);
checkValidity();
FlowRuleEvent event = store.addOrUpdateFlowRule(flowRule);
if (event == null) {
log.debug("Flow {} updated", flowRule);
} else {
log.debug("Flow {} added", flowRule);
post(event);
}
}
// Posts the specified event to the local event dispatcher.
private void post(FlowRuleEvent event) {
if (event != null) {
eventDispatcher.post(event);
}
}
}
}
......
package org.onlab.onos.net.trivial.flow.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.flow.DefaultFlowEntry;
import org.onlab.onos.net.flow.FlowEntry;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.FlowRuleEvent;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
/**
* Manages inventory of flow rules using trivial in-memory implementation.
*/
public class SimpleFlowRuleStore {
// store entries as a pile of rules, no info about device tables
private final Multimap<DeviceId, FlowEntry> flowEntries = HashMultimap.create();
/**
* Returns the flow entries associated with a device.
*
* @param deviceId the device ID
* @return the flow entries
*/
Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
return ImmutableSet.copyOf(flowEntries.get(deviceId));
}
/**
* Stores a new flow rule, and generates a FlowEntry for it.
*
* @param rule the flow rule to add
* @return a flow entry
*/
FlowEntry storeFlowRule(FlowRule rule) {
DeviceId did = rule.deviceId();
FlowEntry entry = new DefaultFlowEntry(did,
rule.selector(), rule.treatment(), rule.priority());
flowEntries.put(did, entry);
return entry;
}
/**
* Stores a new flow rule, or updates an existing entry.
*
* @param rule the flow rule to add or update
* @return flow_added event, or null if just an update
*/
FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
DeviceId did = rule.deviceId();
// check if this new rule is an update to an existing entry
for (FlowEntry fe : flowEntries.get(did)) {
if (rule.equals(fe)) {
// TODO update the stats on this flowEntry?
return null;
}
}
FlowEntry newfe = new DefaultFlowEntry(did,
rule.selector(), rule.treatment(), rule.priority());
flowEntries.put(did, newfe);
return new FlowRuleEvent(RULE_ADDED, rule);
}
/**
*
* @param rule the flow rule to remove
* @return flow_removed event, or null if nothing removed
*/
FlowRuleEvent removeFlowRule(FlowRule rule) {
synchronized (this) {
if (flowEntries.remove(rule.deviceId(), rule)) {
return new FlowRuleEvent(RULE_REMOVED, rule);
} else {
return null;
}
}
}
}
......@@ -106,7 +106,7 @@ public class SimpleHostStore {
* Removes the specified host from the inventory.
*
* @param hostId host identification
* @return remove even or null if host was not found
* @return remove event or null if host was not found
*/
HostEvent removeHost(HostId hostId) {
synchronized (this) {
......
......@@ -7,6 +7,8 @@ import java.util.Arrays;
*/
public final class IpAddress {
// TODO a comparator for netmasks? E.g. for sorting by prefix match order.
//IP Versions
public enum Version { INET, INET6 };
......@@ -99,7 +101,8 @@ public final class IpAddress {
/**
* Converts a dotted-decimal string (x.x.x.x) into an IPv4 address. The
* string can also be in CIDR (slash) notation.
* string can also be in CIDR (slash) notation. If the netmask is omitted,
* it will be set to DEFAULT_MASK (0).
*
* @param address a IP address in string form, e.g. "10.0.0.1", "10.0.0.1/24"
* @return an IP address
......