Ayaka Koshibe

added simple storage to SimpleFlowRuleManager

Change-Id: I7f9117c534673b00f2822cf90bd63d52b95d2704
1 +package org.onlab.onos.net.flow;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +
5 +public class DefaultFlowEntry extends DefaultFlowRule implements FlowEntry {
6 +
7 + private final int priority;
8 + private final long created;
9 + private final FlowId id;
10 +
11 + public DefaultFlowEntry(DefaultFlowEntry entry) {
12 + super(entry.deviceId(), entry.selector(), entry.treatment());
13 + this.priority = entry.priority;
14 + this.created = entry.created;
15 + this.id = entry.id;
16 + }
17 +
18 + public DefaultFlowEntry(DeviceId deviceId, TrafficSelector selector,
19 + TrafficTreatment treatment, int priority) {
20 + super(deviceId, selector, treatment);
21 + this.priority = priority;
22 + this.created = System.currentTimeMillis();
23 + this.id = FlowId.valueOf(this.hashCode());
24 + }
25 +
26 + @Override
27 + public FlowId id() {
28 + return null;
29 + }
30 +
31 + @Override
32 + public int priority() {
33 + return priority;
34 + }
35 +
36 + @Override
37 + public long lifeMillis() {
38 + return (created - System.currentTimeMillis());
39 + }
40 +
41 + @Override
42 + public long idleMillis() {
43 + return 0;
44 + }
45 +
46 + @Override
47 + public long packets() {
48 + return 0;
49 + }
50 +
51 + @Override
52 + public long bytes() {
53 + return 0;
54 + }
55 +
56 + @Override
57 + /*
58 + * currently uses the parts that definitely have a defined hashcode...
59 + *
60 + * (non-Javadoc)
61 + * @see java.lang.Object#hashCode()
62 + */
63 + public int hashCode() {
64 + final int prime = 31;
65 + int result = prime * this.deviceId().hashCode();
66 + result = prime * result + Long.valueOf(this.created).hashCode();
67 + return result;
68 + }
69 +
70 + @Override
71 + /*
72 + * The priority and statistics can change on a given treatment and selector
73 + *
74 + * (non-Javadoc)
75 + * @see java.lang.Object#equals(java.lang.Object)
76 + */
77 + public boolean equals(Object obj) {
78 + if (obj instanceof DefaultFlowEntry) {
79 + DefaultFlowEntry that = (DefaultFlowEntry) obj;
80 + if (!this.id.equals(that.id())) {
81 + return false;
82 + }
83 + return super.equals(obj);
84 + }
85 + return false;
86 + }
87 +
88 +}
...@@ -35,4 +35,37 @@ public class DefaultFlowRule implements FlowRule { ...@@ -35,4 +35,37 @@ public class DefaultFlowRule implements FlowRule {
35 return treatment; 35 return treatment;
36 } 36 }
37 37
38 + @Override
39 + public int hashCode() {
40 + final int prime = 31;
41 + int result = prime * this.deviceId().hashCode();
42 + result = prime * result + selector.hashCode();
43 + result = prime * result + treatment.hashCode();
44 + return result;
45 + }
46 +
47 + @Override
48 + /*
49 + * The priority and statistics can change on a given treatment and selector
50 + *
51 + * (non-Javadoc)
52 + * @see java.lang.Object#equals(java.lang.Object)
53 + */
54 + public boolean equals(Object obj) {
55 + if (obj instanceof FlowRule) {
56 + DefaultFlowRule that = (DefaultFlowRule) obj;
57 + if (!this.deviceId().equals(that.deviceId())) {
58 + return false;
59 + }
60 + if (!this.treatment().equals(that.treatment())) {
61 + return false;
62 + }
63 + if (!this.selector().equals(that.selector())) {
64 + return false;
65 + }
66 + }
67 + return true;
68 + }
69 +
70 +
38 } 71 }
......
...@@ -5,7 +5,11 @@ package org.onlab.onos.net.flow; ...@@ -5,7 +5,11 @@ package org.onlab.onos.net.flow;
5 */ 5 */
6 public interface FlowEntry extends FlowRule { 6 public interface FlowEntry extends FlowRule {
7 7
8 - 8 + /**
9 + * Returns the ID of this flow.
10 + *
11 + * @return the flow ID
12 + */
9 FlowId id(); 13 FlowId id();
10 14
11 /** 15 /**
......
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 +import java.util.List;
4 +
3 import org.onlab.onos.net.DeviceId; 5 import org.onlab.onos.net.DeviceId;
4 6
5 /** 7 /**
...@@ -30,7 +32,7 @@ public interface FlowRuleService { ...@@ -30,7 +32,7 @@ public interface FlowRuleService {
30 * throws SomeKindOfException that indicates which ones were applied and 32 * throws SomeKindOfException that indicates which ones were applied and
31 * which ones failed 33 * which ones failed
32 */ 34 */
33 - void applyFlowRules(FlowRule... flowRules); 35 + List<FlowEntry> applyFlowRules(FlowRule... flowRules);
34 36
35 /** 37 /**
36 * Removes the specified flow rules from their respective devices. If the 38 * Removes the specified flow rules from their respective devices. If the
......
...@@ -2,6 +2,9 @@ package org.onlab.onos.net.trivial.flow.impl; ...@@ -2,6 +2,9 @@ package org.onlab.onos.net.trivial.flow.impl;
2 2
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
5 +import java.util.ArrayList;
6 +import java.util.List;
7 +
5 import org.apache.felix.scr.annotations.Activate; 8 import org.apache.felix.scr.annotations.Activate;
6 import org.apache.felix.scr.annotations.Component; 9 import org.apache.felix.scr.annotations.Component;
7 import org.apache.felix.scr.annotations.Deactivate; 10 import org.apache.felix.scr.annotations.Deactivate;
...@@ -25,17 +28,22 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; ...@@ -25,17 +28,22 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry;
25 import org.onlab.onos.net.provider.AbstractProviderService; 28 import org.onlab.onos.net.provider.AbstractProviderService;
26 import org.slf4j.Logger; 29 import org.slf4j.Logger;
27 30
31 +import static com.google.common.base.Preconditions.checkNotNull;
32 +
28 @Component(immediate = true) 33 @Component(immediate = true)
29 @Service 34 @Service
30 public class SimpleFlowRuleManager 35 public class SimpleFlowRuleManager
31 extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService> 36 extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
32 implements FlowRuleService, FlowRuleProviderRegistry { 37 implements FlowRuleService, FlowRuleProviderRegistry {
33 38
39 + public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
34 private final Logger log = getLogger(getClass()); 40 private final Logger log = getLogger(getClass());
35 41
36 private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener> 42 private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
37 listenerRegistry = new AbstractListenerRegistry<>(); 43 listenerRegistry = new AbstractListenerRegistry<>();
38 44
45 + private final SimpleFlowRuleStore store = new SimpleFlowRuleStore();
46 +
39 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 47 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
40 private EventDeliveryService eventDispatcher; 48 private EventDeliveryService eventDispatcher;
41 49
...@@ -56,30 +64,31 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -56,30 +64,31 @@ implements FlowRuleService, FlowRuleProviderRegistry {
56 64
57 @Override 65 @Override
58 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) { 66 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
59 - //TODO: store rules somewhere and return them here 67 + return store.getFlowEntries(deviceId);
60 - return null;
61 } 68 }
62 69
63 @Override 70 @Override
64 - public void applyFlowRules(FlowRule... flowRules) { 71 + public List<FlowEntry> applyFlowRules(FlowRule... flowRules) {
72 + List<FlowEntry> entries = new ArrayList<FlowEntry>();
73 +
65 for (int i = 0; i < flowRules.length; i++) { 74 for (int i = 0; i < flowRules.length; i++) {
66 - FlowRule f = flowRules[0]; 75 + FlowRule f = flowRules[i];
67 final Device device = deviceService.getDevice(f.deviceId()); 76 final Device device = deviceService.getDevice(f.deviceId());
68 final FlowRuleProvider frp = getProvider(device.providerId()); 77 final FlowRuleProvider frp = getProvider(device.providerId());
69 - //TODO: store rules somewhere 78 + entries.add(store.storeFlowRule(f));
70 frp.applyFlowRule(f); 79 frp.applyFlowRule(f);
71 } 80 }
72 81
73 - 82 + return entries;
74 } 83 }
75 84
76 @Override 85 @Override
77 public void removeFlowRules(FlowRule... flowRules) { 86 public void removeFlowRules(FlowRule... flowRules) {
78 for (int i = 0; i < flowRules.length; i++) { 87 for (int i = 0; i < flowRules.length; i++) {
79 - FlowRule f = flowRules[0]; 88 + FlowRule f = flowRules[i];
80 final Device device = deviceService.getDevice(f.deviceId()); 89 final Device device = deviceService.getDevice(f.deviceId());
81 final FlowRuleProvider frp = getProvider(device.providerId()); 90 final FlowRuleProvider frp = getProvider(device.providerId());
82 - //TODO: remove stored rules from wherever they are 91 + store.removeFlowRule(f);
83 frp.removeFlowRule(f); 92 frp.removeFlowRule(f);
84 } 93 }
85 94
...@@ -111,22 +120,44 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -111,22 +120,44 @@ implements FlowRuleService, FlowRuleProviderRegistry {
111 120
112 @Override 121 @Override
113 public void flowRemoved(FlowRule flowRule) { 122 public void flowRemoved(FlowRule flowRule) {
114 - // TODO Auto-generated method stub 123 + checkNotNull(flowRule, FLOW_RULE_NULL);
124 + checkValidity();
125 + FlowRuleEvent event = store.removeFlowRule(flowRule);
115 126
127 + if (event != null) {
128 + log.debug("Flow {} removed", flowRule);
129 + post(event);
130 + }
116 } 131 }
117 132
118 @Override 133 @Override
119 public void flowMissing(FlowRule flowRule) { 134 public void flowMissing(FlowRule flowRule) {
135 + checkNotNull(flowRule, FLOW_RULE_NULL);
136 + checkValidity();
120 // TODO Auto-generated method stub 137 // TODO Auto-generated method stub
121 138
122 } 139 }
123 140
124 @Override 141 @Override
125 public void flowAdded(FlowRule flowRule) { 142 public void flowAdded(FlowRule flowRule) {
126 - // TODO Auto-generated method stub 143 + checkNotNull(flowRule, FLOW_RULE_NULL);
127 - 144 + checkValidity();
145 +
146 + FlowRuleEvent event = store.addOrUpdateFlowRule(flowRule);
147 + if (event == null) {
148 + log.debug("Flow {} updated", flowRule);
149 + } else {
150 + log.debug("Flow {} added", flowRule);
151 + post(event);
152 + }
128 } 153 }
129 154
155 + // Posts the specified event to the local event dispatcher.
156 + private void post(FlowRuleEvent event) {
157 + if (event != null) {
158 + eventDispatcher.post(event);
159 + }
160 + }
130 } 161 }
131 162
132 } 163 }
......
1 +package org.onlab.onos.net.trivial.flow.impl;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +import org.onlab.onos.net.flow.DefaultFlowEntry;
5 +import org.onlab.onos.net.flow.FlowEntry;
6 +import org.onlab.onos.net.flow.FlowRule;
7 +import org.onlab.onos.net.flow.FlowRuleEvent;
8 +
9 +import com.google.common.collect.HashMultimap;
10 +import com.google.common.collect.ImmutableSet;
11 +import com.google.common.collect.Multimap;
12 +
13 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
14 +
15 +/**
16 + * Manages inventory of flow rules using trivial in-memory implementation.
17 + */
18 +public class SimpleFlowRuleStore {
19 +
20 + // store entries as a pile of rules, no info about device tables
21 + private final Multimap<DeviceId, FlowEntry> flowEntries = HashMultimap.create();
22 +
23 + /**
24 + * Returns the flow entries associated with a device.
25 + *
26 + * @param deviceId the device ID
27 + * @return the flow entries
28 + */
29 + Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
30 + return ImmutableSet.copyOf(flowEntries.get(deviceId));
31 + }
32 +
33 + /**
34 + * Stores a new flow rule, and generates a FlowEntry for it.
35 + *
36 + * @param rule the flow rule to add
37 + * @return a flow entry
38 + */
39 + FlowEntry storeFlowRule(FlowRule rule) {
40 + DeviceId did = rule.deviceId();
41 + FlowEntry entry = new DefaultFlowEntry(did,
42 + rule.selector(), rule.treatment(), rule.priority());
43 + flowEntries.put(did, entry);
44 + return entry;
45 + }
46 +
47 + /**
48 + * Stores a new flow rule, or updates an existing entry.
49 + *
50 + * @param rule the flow rule to add or update
51 + * @return flow_added event, or null if just an update
52 + */
53 + FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
54 + DeviceId did = rule.deviceId();
55 +
56 + // check if this new rule is an update to an existing entry
57 + for (FlowEntry fe : flowEntries.get(did)) {
58 + if (rule.equals(fe)) {
59 + // TODO update the stats on this flowEntry?
60 + return null;
61 + }
62 + }
63 +
64 + FlowEntry newfe = new DefaultFlowEntry(did,
65 + rule.selector(), rule.treatment(), rule.priority());
66 + flowEntries.put(did, newfe);
67 + return new FlowRuleEvent(RULE_ADDED, rule);
68 + }
69 +
70 + /**
71 + *
72 + * @param rule the flow rule to remove
73 + * @return flow_removed event, or null if nothing removed
74 + */
75 + FlowRuleEvent removeFlowRule(FlowRule rule) {
76 + synchronized (this) {
77 + if (flowEntries.remove(rule.deviceId(), rule)) {
78 + return new FlowRuleEvent(RULE_REMOVED, rule);
79 + } else {
80 + return null;
81 + }
82 + }
83 + }
84 +
85 +}
...@@ -106,7 +106,7 @@ public class SimpleHostStore { ...@@ -106,7 +106,7 @@ public class SimpleHostStore {
106 * Removes the specified host from the inventory. 106 * Removes the specified host from the inventory.
107 * 107 *
108 * @param hostId host identification 108 * @param hostId host identification
109 - * @return remove even or null if host was not found 109 + * @return remove event or null if host was not found
110 */ 110 */
111 HostEvent removeHost(HostId hostId) { 111 HostEvent removeHost(HostId hostId) {
112 synchronized (this) { 112 synchronized (this) {
......
...@@ -7,6 +7,8 @@ import java.util.Arrays; ...@@ -7,6 +7,8 @@ import java.util.Arrays;
7 */ 7 */
8 public final class IpAddress { 8 public final class IpAddress {
9 9
10 + // TODO a comparator for netmasks? E.g. for sorting by prefix match order.
11 +
10 //IP Versions 12 //IP Versions
11 public enum Version { INET, INET6 }; 13 public enum Version { INET, INET6 };
12 14
...@@ -99,7 +101,8 @@ public final class IpAddress { ...@@ -99,7 +101,8 @@ public final class IpAddress {
99 101
100 /** 102 /**
101 * Converts a dotted-decimal string (x.x.x.x) into an IPv4 address. The 103 * Converts a dotted-decimal string (x.x.x.x) into an IPv4 address. The
102 - * string can also be in CIDR (slash) notation. 104 + * string can also be in CIDR (slash) notation. If the netmask is omitted,
105 + * it will be set to DEFAULT_MASK (0).
103 * 106 *
104 * @param address a IP address in string form, e.g. "10.0.0.1", "10.0.0.1/24" 107 * @param address a IP address in string form, e.g. "10.0.0.1", "10.0.0.1/24"
105 * @return an IP address 108 * @return an IP address
......