Committed by
Gerrit Code Review
OpenFlow Meter Provider - still need to parse meter stats
Change-Id: I4b313ea003b3801f81ec7d4823bf69de37fd8643
Showing
9 changed files
with
599 additions
and
10 deletions
... | @@ -32,7 +32,7 @@ public interface Band { | ... | @@ -32,7 +32,7 @@ public interface Band { |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * defines a simple DiffServ policer that remark | 34 | * defines a simple DiffServ policer that remark |
35 | - * the drop precedence of the DSCP eld in the | 35 | + * the drop precedence of the DSCP field in the |
36 | * IP header of the packets that exceed the band | 36 | * IP header of the packets that exceed the band |
37 | * rate value. | 37 | * rate value. |
38 | */ | 38 | */ |
... | @@ -42,16 +42,32 @@ public interface Band { | ... | @@ -42,16 +42,32 @@ public interface Band { |
42 | /** | 42 | /** |
43 | * The rate at which this meter applies. | 43 | * The rate at which this meter applies. |
44 | * | 44 | * |
45 | - * @return the integer value of the rate | 45 | + * @return the long value of the rate |
46 | */ | 46 | */ |
47 | - int rate(); | 47 | + long rate(); |
48 | 48 | ||
49 | /** | 49 | /** |
50 | * The burst size at which the meter applies. | 50 | * The burst size at which the meter applies. |
51 | * | 51 | * |
52 | - * @return the integer value of the size | 52 | + * @return the long value of the size |
53 | */ | 53 | */ |
54 | - int burst(); | 54 | + long burst(); |
55 | + | ||
56 | + /** | ||
57 | + * Only meaningful in the case of a REMARK band type. | ||
58 | + * indicates by which amount the drop precedence of | ||
59 | + * the packet should be increase if the band is exceeded. | ||
60 | + * | ||
61 | + * @return a short value | ||
62 | + */ | ||
63 | + short dropPrecedence(); | ||
64 | + | ||
65 | + /** | ||
66 | + * Signals the type of band to create. | ||
67 | + * | ||
68 | + * @return a band type | ||
69 | + */ | ||
70 | + Type type(); | ||
55 | 71 | ||
56 | 72 | ||
57 | } | 73 | } | ... | ... |
... | @@ -38,5 +38,52 @@ public enum MeterFailReason { | ... | @@ -38,5 +38,52 @@ public enum MeterFailReason { |
38 | /** | 38 | /** |
39 | * The meter that was attempted to be modified is unknown. | 39 | * The meter that was attempted to be modified is unknown. |
40 | */ | 40 | */ |
41 | - UNKNOWN | 41 | + UNKNOWN, |
42 | + | ||
43 | + /** | ||
44 | + * The operation for this meter installation timed out. | ||
45 | + */ | ||
46 | + TIMEOUT, | ||
47 | + | ||
48 | + /** | ||
49 | + * Invalid meter definition. | ||
50 | + */ | ||
51 | + INVALID_METER, | ||
52 | + | ||
53 | + /** | ||
54 | + * The target device is unknown. | ||
55 | + */ | ||
56 | + UNKNOWN_DEVICE, | ||
57 | + | ||
58 | + /** | ||
59 | + * Unknown command. | ||
60 | + */ | ||
61 | + UNKNOWN_COMMAND, | ||
62 | + | ||
63 | + /** | ||
64 | + * Unknown flags. | ||
65 | + */ | ||
66 | + UNKNOWN_FLAGS, | ||
67 | + | ||
68 | + /** | ||
69 | + * Bad rate value. | ||
70 | + */ | ||
71 | + BAD_RATE, | ||
72 | + | ||
73 | + /** | ||
74 | + * Bad burst size value. | ||
75 | + */ | ||
76 | + BAD_BURST, | ||
77 | + | ||
78 | + /** | ||
79 | + * Bad band. | ||
80 | + */ | ||
81 | + BAD_BAND, | ||
82 | + | ||
83 | + /** | ||
84 | + * Bad value value. | ||
85 | + */ | ||
86 | + BAD_BAND_VALUE | ||
87 | + | ||
88 | + | ||
42 | } | 89 | } | ... | ... |
... | @@ -29,10 +29,10 @@ public interface MeterProviderService extends ProviderService<MeterProvider> { | ... | @@ -29,10 +29,10 @@ public interface MeterProviderService extends ProviderService<MeterProvider> { |
29 | /** | 29 | /** |
30 | * Notifies the core that a meter operaton failed for a | 30 | * Notifies the core that a meter operaton failed for a |
31 | * specific reason. | 31 | * specific reason. |
32 | - * @param deviceId | 32 | + * @param operation the failed operation |
33 | - * @param operation | 33 | + * @param reason the failure reason |
34 | */ | 34 | */ |
35 | - void meterOperationFailed(DeviceId deviceId, MeterOperation operation, | 35 | + void meterOperationFailed(MeterOperation operation, |
36 | MeterFailReason reason); | 36 | MeterFailReason reason); |
37 | 37 | ||
38 | /** | 38 | /** | ... | ... |
... | @@ -29,4 +29,5 @@ | ... | @@ -29,4 +29,5 @@ |
29 | <artifact>mvn:${project.groupId}/onos-of-provider-packet/${project.version}</artifact> | 29 | <artifact>mvn:${project.groupId}/onos-of-provider-packet/${project.version}</artifact> |
30 | <artifact>mvn:${project.groupId}/onos-of-provider-flow/${project.version}</artifact> | 30 | <artifact>mvn:${project.groupId}/onos-of-provider-flow/${project.version}</artifact> |
31 | <artifact>mvn:${project.groupId}/onos-of-provider-group/${project.version}</artifact> | 31 | <artifact>mvn:${project.groupId}/onos-of-provider-group/${project.version}</artifact> |
32 | + <artifact>mvn:${project.groupId}/onos-of-provider-meter/${project.version}</artifact> | ||
32 | </app> | 33 | </app> | ... | ... |
... | @@ -29,5 +29,6 @@ | ... | @@ -29,5 +29,6 @@ |
29 | <bundle>mvn:${project.groupId}/onos-of-provider-packet/${project.version}</bundle> | 29 | <bundle>mvn:${project.groupId}/onos-of-provider-packet/${project.version}</bundle> |
30 | <bundle>mvn:${project.groupId}/onos-of-provider-flow/${project.version}</bundle> | 30 | <bundle>mvn:${project.groupId}/onos-of-provider-flow/${project.version}</bundle> |
31 | <bundle>mvn:${project.groupId}/onos-of-provider-group/${project.version}</bundle> | 31 | <bundle>mvn:${project.groupId}/onos-of-provider-group/${project.version}</bundle> |
32 | + <bundle>mvn:${project.groupId}/onos-of-provider-meter/${project.version}</bundle> | ||
32 | </feature> | 33 | </feature> |
33 | </features> | 34 | </features> | ... | ... |
providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.provider.of.meter.impl; | ||
17 | + | ||
18 | +import org.onosproject.net.meter.Band; | ||
19 | +import org.onosproject.net.meter.Meter; | ||
20 | +import org.onosproject.net.meter.MeterId; | ||
21 | +import org.projectfloodlight.openflow.protocol.OFFactory; | ||
22 | +import org.projectfloodlight.openflow.protocol.OFMeterFlags; | ||
23 | +import org.projectfloodlight.openflow.protocol.OFMeterMod; | ||
24 | +import org.projectfloodlight.openflow.protocol.OFMeterModCommand; | ||
25 | +import org.projectfloodlight.openflow.protocol.meterband.OFMeterBand; | ||
26 | +import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandDrop; | ||
27 | +import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandDscpRemark; | ||
28 | +import org.slf4j.Logger; | ||
29 | + | ||
30 | +import java.util.Collection; | ||
31 | +import java.util.List; | ||
32 | +import java.util.stream.Collectors; | ||
33 | + | ||
34 | +import static com.google.common.base.Preconditions.checkArgument; | ||
35 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
36 | +import static org.slf4j.LoggerFactory.getLogger; | ||
37 | + | ||
38 | +/** | ||
39 | + * Builder for a meter modification. | ||
40 | + */ | ||
41 | +public final class MeterModBuilder { | ||
42 | + | ||
43 | + private final Logger log = getLogger(getClass()); | ||
44 | + | ||
45 | + private final long xid; | ||
46 | + private final OFFactory factory; | ||
47 | + private Meter.Unit unit = Meter.Unit.KB_PER_SEC; | ||
48 | + private boolean burst = false; | ||
49 | + private Integer id; | ||
50 | + private Collection<Band> bands; | ||
51 | + | ||
52 | + public MeterModBuilder(long xid, OFFactory factory) { | ||
53 | + this.xid = xid; | ||
54 | + this.factory = factory; | ||
55 | + } | ||
56 | + | ||
57 | + public static MeterModBuilder builder(long xid, OFFactory factory) { | ||
58 | + return new MeterModBuilder(xid, factory); | ||
59 | + } | ||
60 | + | ||
61 | + public MeterModBuilder withRateUnit(Meter.Unit unit) { | ||
62 | + this.unit = unit; | ||
63 | + return this; | ||
64 | + } | ||
65 | + | ||
66 | + public MeterModBuilder burst() { | ||
67 | + this.burst = true; | ||
68 | + return this; | ||
69 | + } | ||
70 | + | ||
71 | + public MeterModBuilder withId(MeterId meterId) { | ||
72 | + this.id = meterId.id(); | ||
73 | + return this; | ||
74 | + } | ||
75 | + | ||
76 | + public MeterModBuilder withBands(Collection<Band> bands) { | ||
77 | + this.bands = bands; | ||
78 | + return this; | ||
79 | + } | ||
80 | + | ||
81 | + public OFMeterMod add() { | ||
82 | + validate(); | ||
83 | + OFMeterMod.Builder builder = builderMeterMod(); | ||
84 | + builder.setCommand(OFMeterModCommand.ADD.ordinal()); | ||
85 | + return builder.build(); | ||
86 | + } | ||
87 | + | ||
88 | + public OFMeterMod remove() { | ||
89 | + validate(); | ||
90 | + OFMeterMod.Builder builder = builderMeterMod(); | ||
91 | + builder.setCommand(OFMeterModCommand.DELETE.ordinal()); | ||
92 | + return builder.build(); | ||
93 | + } | ||
94 | + | ||
95 | + public OFMeterMod modify() { | ||
96 | + validate(); | ||
97 | + OFMeterMod.Builder builder = builderMeterMod(); | ||
98 | + builder.setCommand(OFMeterModCommand.MODIFY.ordinal()); | ||
99 | + return builder.build(); | ||
100 | + } | ||
101 | + | ||
102 | + private OFMeterMod.Builder builderMeterMod() { | ||
103 | + OFMeterMod.Builder builder = factory.buildMeterMod(); | ||
104 | + int flags = 0; | ||
105 | + if (burst) { | ||
106 | + // covering loxi short comings. | ||
107 | + flags |= 1 << OFMeterFlags.BURST.ordinal(); | ||
108 | + } | ||
109 | + switch (unit) { | ||
110 | + case PKTS_PER_SEC: | ||
111 | + flags |= 1 << OFMeterFlags.PKTPS.ordinal(); | ||
112 | + break; | ||
113 | + case KB_PER_SEC: | ||
114 | + flags |= 1 << OFMeterFlags.KBPS.ordinal(); | ||
115 | + break; | ||
116 | + default: | ||
117 | + log.warn("Unknown unit type {}", unit); | ||
118 | + } | ||
119 | + builder.setBands(buildBands()); | ||
120 | + builder.setFlags(flags) | ||
121 | + .setMeterId(id) | ||
122 | + .setXid(xid); | ||
123 | + return builder; | ||
124 | + } | ||
125 | + | ||
126 | + private List<OFMeterBand> buildBands() { | ||
127 | + return bands.stream().map(b -> { | ||
128 | + switch (b.type()) { | ||
129 | + case DROP: | ||
130 | + OFMeterBandDrop.Builder dropBuilder = | ||
131 | + factory.meterBands().buildDrop(); | ||
132 | + if (burst) { | ||
133 | + dropBuilder.setBurstSize(b.burst()); | ||
134 | + } | ||
135 | + dropBuilder.setRate(b.rate()); | ||
136 | + return dropBuilder.build(); | ||
137 | + case REMARK: | ||
138 | + OFMeterBandDscpRemark.Builder remarkBand = | ||
139 | + factory.meterBands().buildDscpRemark(); | ||
140 | + if (burst) { | ||
141 | + remarkBand.setBurstSize(b.burst()); | ||
142 | + } | ||
143 | + remarkBand.setRate(b.rate()); | ||
144 | + remarkBand.setPrecLevel(b.dropPrecedence()); | ||
145 | + return remarkBand.build(); | ||
146 | + default: | ||
147 | + log.warn("Unknown band type {}", b.type()); | ||
148 | + return null; | ||
149 | + } | ||
150 | + }).filter(value -> value != null).collect(Collectors.toList()); | ||
151 | + } | ||
152 | + | ||
153 | + private void validate() { | ||
154 | + checkNotNull(id, "id cannot be null"); | ||
155 | + checkNotNull(bands, "Must have bands"); | ||
156 | + checkArgument(bands.size() > 0, "Must have at lease one band"); | ||
157 | + } | ||
158 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.provider.of.meter.impl; | ||
18 | + | ||
19 | +import org.jboss.netty.util.HashedWheelTimer; | ||
20 | +import org.jboss.netty.util.Timeout; | ||
21 | +import org.jboss.netty.util.TimerTask; | ||
22 | +import org.onlab.util.Timer; | ||
23 | +import org.onosproject.openflow.controller.OpenFlowSwitch; | ||
24 | +import org.onosproject.openflow.controller.RoleState; | ||
25 | +import org.projectfloodlight.openflow.protocol.OFMeterStatsRequest; | ||
26 | +import org.slf4j.Logger; | ||
27 | + | ||
28 | +import java.util.concurrent.TimeUnit; | ||
29 | + | ||
30 | +import static org.slf4j.LoggerFactory.getLogger; | ||
31 | + | ||
32 | +/* | ||
33 | + * Sends Meter Stats Request and collect the Meter statistics with a time interval. | ||
34 | + */ | ||
35 | +public class MeterStatsCollector implements TimerTask { | ||
36 | + | ||
37 | + private final HashedWheelTimer timer = Timer.getTimer(); | ||
38 | + private final OpenFlowSwitch sw; | ||
39 | + private final Logger log = getLogger(getClass()); | ||
40 | + private final int refreshInterval; | ||
41 | + | ||
42 | + private Timeout timeout; | ||
43 | + | ||
44 | + private boolean stopTimer = false; | ||
45 | + | ||
46 | + /** | ||
47 | + * Creates a GroupStatsCollector object. | ||
48 | + * | ||
49 | + * @param sw Open Flow switch | ||
50 | + * @param interval time interval for collecting group statistic | ||
51 | + */ | ||
52 | + public MeterStatsCollector(OpenFlowSwitch sw, int interval) { | ||
53 | + this.sw = sw; | ||
54 | + this.refreshInterval = interval; | ||
55 | + } | ||
56 | + | ||
57 | + @Override | ||
58 | + public void run(Timeout timeout) throws Exception { | ||
59 | + log.trace("Collecting stats for {}", sw.getStringId()); | ||
60 | + | ||
61 | + sendMeterStatistic(); | ||
62 | + | ||
63 | + if (!this.stopTimer) { | ||
64 | + log.trace("Scheduling stats collection in {} seconds for {}", | ||
65 | + this.refreshInterval, this.sw.getStringId()); | ||
66 | + timeout.getTimer().newTimeout(this, refreshInterval, | ||
67 | + TimeUnit.SECONDS); | ||
68 | + } | ||
69 | + } | ||
70 | + | ||
71 | + private void sendMeterStatistic() { | ||
72 | + if (log.isTraceEnabled()) { | ||
73 | + log.trace("sendMeterStatistics {}:{}", sw.getStringId(), sw.getRole()); | ||
74 | + } | ||
75 | + if (sw.getRole() != RoleState.MASTER) { | ||
76 | + return; | ||
77 | + } | ||
78 | + | ||
79 | + OFMeterStatsRequest.Builder builder = | ||
80 | + sw.factory().buildMeterStatsRequest(); | ||
81 | + builder.setXid(0).setMeterId(0xFFFFFFFF); | ||
82 | + | ||
83 | + sw.sendMsg(builder.build()); | ||
84 | + | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * Starts the collector. | ||
89 | + */ | ||
90 | + public void start() { | ||
91 | + log.info("Starting Meter Stats collection thread for {}", sw.getStringId()); | ||
92 | + timeout = timer.newTimeout(this, 1, TimeUnit.SECONDS); | ||
93 | + } | ||
94 | + | ||
95 | + /** | ||
96 | + * Stops the collector. | ||
97 | + */ | ||
98 | + public void stop() { | ||
99 | + log.info("Stopping Meter Stats collection thread for {}", sw.getStringId()); | ||
100 | + this.stopTimer = true; | ||
101 | + timeout.cancel(); | ||
102 | + } | ||
103 | +} |
... | @@ -16,18 +16,45 @@ | ... | @@ -16,18 +16,45 @@ |
16 | 16 | ||
17 | package org.onosproject.provider.of.meter.impl; | 17 | package org.onosproject.provider.of.meter.impl; |
18 | 18 | ||
19 | +import com.google.common.cache.Cache; | ||
20 | +import com.google.common.cache.CacheBuilder; | ||
21 | +import com.google.common.cache.RemovalCause; | ||
22 | +import com.google.common.cache.RemovalNotification; | ||
23 | +import com.google.common.collect.Maps; | ||
24 | +import org.apache.felix.scr.annotations.Activate; | ||
19 | import org.apache.felix.scr.annotations.Component; | 25 | import org.apache.felix.scr.annotations.Component; |
26 | +import org.apache.felix.scr.annotations.Deactivate; | ||
20 | import org.apache.felix.scr.annotations.Reference; | 27 | import org.apache.felix.scr.annotations.Reference; |
21 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 28 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
22 | import org.onosproject.net.DeviceId; | 29 | import org.onosproject.net.DeviceId; |
30 | +import org.onosproject.net.meter.Meter; | ||
31 | +import org.onosproject.net.meter.MeterFailReason; | ||
23 | import org.onosproject.net.meter.MeterOperation; | 32 | import org.onosproject.net.meter.MeterOperation; |
24 | import org.onosproject.net.meter.MeterOperations; | 33 | import org.onosproject.net.meter.MeterOperations; |
25 | import org.onosproject.net.meter.MeterProvider; | 34 | import org.onosproject.net.meter.MeterProvider; |
35 | +import org.onosproject.net.meter.MeterProviderRegistry; | ||
36 | +import org.onosproject.net.meter.MeterProviderService; | ||
26 | import org.onosproject.net.provider.AbstractProvider; | 37 | import org.onosproject.net.provider.AbstractProvider; |
27 | import org.onosproject.net.provider.ProviderId; | 38 | import org.onosproject.net.provider.ProviderId; |
39 | +import org.onosproject.openflow.controller.Dpid; | ||
28 | import org.onosproject.openflow.controller.OpenFlowController; | 40 | import org.onosproject.openflow.controller.OpenFlowController; |
41 | +import org.onosproject.openflow.controller.OpenFlowEventListener; | ||
42 | +import org.onosproject.openflow.controller.OpenFlowSwitch; | ||
43 | +import org.onosproject.openflow.controller.OpenFlowSwitchListener; | ||
44 | +import org.onosproject.openflow.controller.RoleState; | ||
45 | +import org.projectfloodlight.openflow.protocol.OFErrorMsg; | ||
46 | +import org.projectfloodlight.openflow.protocol.OFErrorType; | ||
47 | +import org.projectfloodlight.openflow.protocol.OFMessage; | ||
48 | +import org.projectfloodlight.openflow.protocol.OFPortStatus; | ||
49 | +import org.projectfloodlight.openflow.protocol.OFStatsReply; | ||
50 | +import org.projectfloodlight.openflow.protocol.OFVersion; | ||
51 | +import org.projectfloodlight.openflow.protocol.errormsg.OFMeterModFailedErrorMsg; | ||
29 | import org.slf4j.Logger; | 52 | import org.slf4j.Logger; |
30 | 53 | ||
54 | +import java.util.Map; | ||
55 | +import java.util.concurrent.TimeUnit; | ||
56 | +import java.util.concurrent.atomic.AtomicLong; | ||
57 | + | ||
31 | import static org.slf4j.LoggerFactory.getLogger; | 58 | import static org.slf4j.LoggerFactory.getLogger; |
32 | 59 | ||
33 | /** | 60 | /** |
... | @@ -36,11 +63,28 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -36,11 +63,28 @@ import static org.slf4j.LoggerFactory.getLogger; |
36 | @Component(immediate = true) | 63 | @Component(immediate = true) |
37 | public class OpenFlowMeterProvider extends AbstractProvider implements MeterProvider { | 64 | public class OpenFlowMeterProvider extends AbstractProvider implements MeterProvider { |
38 | 65 | ||
66 | + | ||
39 | private final Logger log = getLogger(getClass()); | 67 | private final Logger log = getLogger(getClass()); |
40 | 68 | ||
41 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 69 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
42 | protected OpenFlowController controller; | 70 | protected OpenFlowController controller; |
43 | 71 | ||
72 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
73 | + protected MeterProviderRegistry providerRegistry; | ||
74 | + | ||
75 | + private MeterProviderService providerService; | ||
76 | + | ||
77 | + private static final AtomicLong XID_COUNTER = new AtomicLong(1); | ||
78 | + | ||
79 | + static final int POLL_INTERVAL = 10; | ||
80 | + static final long TIMEOUT = 30; | ||
81 | + | ||
82 | + private Cache<Integer, MeterOperation> pendingOperations; | ||
83 | + private Cache<Long, MeterOperation> pendingXid; | ||
84 | + | ||
85 | + | ||
86 | + private InternalMeterListener listener = new InternalMeterListener(); | ||
87 | + private Map<Dpid, MeterStatsCollector> collectors = Maps.newHashMap(); | ||
44 | 88 | ||
45 | /** | 89 | /** |
46 | * Creates a OpenFlow meter provider. | 90 | * Creates a OpenFlow meter provider. |
... | @@ -49,13 +93,232 @@ public class OpenFlowMeterProvider extends AbstractProvider implements MeterProv | ... | @@ -49,13 +93,232 @@ public class OpenFlowMeterProvider extends AbstractProvider implements MeterProv |
49 | super(new ProviderId("of", "org.onosproject.provider.meter")); | 93 | super(new ProviderId("of", "org.onosproject.provider.meter")); |
50 | } | 94 | } |
51 | 95 | ||
96 | + @Activate | ||
97 | + public void activate() { | ||
98 | + providerService = providerRegistry.register(this); | ||
99 | + | ||
100 | + pendingOperations = CacheBuilder.newBuilder() | ||
101 | + .expireAfterWrite(TIMEOUT, TimeUnit.SECONDS) | ||
102 | + .removalListener((RemovalNotification<Integer, MeterOperation> notification) -> { | ||
103 | + if (notification.getCause() == RemovalCause.EXPIRED) { | ||
104 | + providerService.meterOperationFailed(notification.getValue(), | ||
105 | + MeterFailReason.TIMEOUT); | ||
106 | + } | ||
107 | + }).build(); | ||
108 | + | ||
109 | + controller.addEventListener(listener); | ||
110 | + controller.addListener(listener); | ||
111 | + | ||
112 | + controller.getSwitches().forEach((sw -> createStatsCollection(sw))); | ||
113 | + } | ||
114 | + | ||
115 | + @Deactivate | ||
116 | + public void deactivate() { | ||
117 | + providerRegistry.unregister(this); | ||
118 | + controller.removeEventListener(listener); | ||
119 | + controller.removeListener(listener); | ||
120 | + providerService = null; | ||
121 | + } | ||
122 | + | ||
52 | @Override | 123 | @Override |
53 | public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) { | 124 | public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) { |
125 | + Dpid dpid = Dpid.dpid(deviceId.uri()); | ||
126 | + OpenFlowSwitch sw = controller.getSwitch(dpid); | ||
127 | + if (sw == null) { | ||
128 | + log.error("Unknown device {}", deviceId); | ||
129 | + meterOps.operations().forEach(op -> | ||
130 | + providerService.meterOperationFailed(op, | ||
131 | + MeterFailReason.UNKNOWN_DEVICE) | ||
132 | + ); | ||
133 | + return; | ||
134 | + } | ||
54 | 135 | ||
136 | + meterOps.operations().forEach(op -> performOperation(sw, op)); | ||
55 | } | 137 | } |
56 | 138 | ||
57 | @Override | 139 | @Override |
58 | public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) { | 140 | public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) { |
141 | + Dpid dpid = Dpid.dpid(deviceId.uri()); | ||
142 | + OpenFlowSwitch sw = controller.getSwitch(dpid); | ||
143 | + if (sw == null) { | ||
144 | + log.error("Unknown device {}", deviceId); | ||
145 | + providerService.meterOperationFailed(meterOp, | ||
146 | + MeterFailReason.UNKNOWN_DEVICE); | ||
147 | + return; | ||
148 | + } | ||
149 | + | ||
150 | + } | ||
151 | + | ||
152 | + private void performOperation(OpenFlowSwitch sw, MeterOperation op) { | ||
153 | + | ||
154 | + pendingOperations.put(op.meter().id().id(), op); | ||
155 | + | ||
156 | + | ||
157 | + Meter meter = op.meter(); | ||
158 | + MeterModBuilder builder = MeterModBuilder.builder(meter.id().id(), sw.factory()); | ||
159 | + if (meter.isBurst()) { | ||
160 | + builder.burst(); | ||
161 | + } | ||
162 | + builder.withBands(meter.bands()) | ||
163 | + .withId(meter.id()) | ||
164 | + .withRateUnit(meter.unit()); | ||
165 | + | ||
166 | + switch (op.type()) { | ||
167 | + case ADD: | ||
168 | + sw.sendMsg(builder.add()); | ||
169 | + break; | ||
170 | + case REMOVE: | ||
171 | + sw.sendMsg(builder.remove()); | ||
172 | + break; | ||
173 | + case MODIFY: | ||
174 | + sw.sendMsg(builder.modify()); | ||
175 | + break; | ||
176 | + default: | ||
177 | + log.warn("Unknown Meter command {}; not sending anything", | ||
178 | + op.type()); | ||
179 | + providerService.meterOperationFailed(op, | ||
180 | + MeterFailReason.UNKNOWN_COMMAND); | ||
181 | + } | ||
59 | 182 | ||
60 | } | 183 | } |
184 | + | ||
185 | + private void createStatsCollection(OpenFlowSwitch sw) { | ||
186 | + if (isMeterSupported(sw)) { | ||
187 | + MeterStatsCollector msc = new MeterStatsCollector(sw, POLL_INTERVAL); | ||
188 | + msc.start(); | ||
189 | + collectors.put(new Dpid(sw.getId()), msc); | ||
190 | + } | ||
191 | + } | ||
192 | + | ||
193 | + private boolean isMeterSupported(OpenFlowSwitch sw) { | ||
194 | + if (sw.factory().getVersion() == OFVersion.OF_10 || | ||
195 | + sw.factory().getVersion() == OFVersion.OF_11 || | ||
196 | + sw.factory().getVersion() == OFVersion.OF_12) { | ||
197 | + return false; | ||
198 | + } | ||
199 | + | ||
200 | + return true; | ||
201 | + } | ||
202 | + | ||
203 | + private void pushMeterStats(Dpid dpid, OFStatsReply msg) { | ||
204 | + | ||
205 | + } | ||
206 | + | ||
207 | + private void signalMeterError(OFMeterModFailedErrorMsg meterError, | ||
208 | + MeterOperation op) { | ||
209 | + switch (meterError.getCode()) { | ||
210 | + case UNKNOWN: | ||
211 | + providerService.meterOperationFailed(op, | ||
212 | + MeterFailReason.UNKNOWN_DEVICE); | ||
213 | + break; | ||
214 | + case METER_EXISTS: | ||
215 | + providerService.meterOperationFailed(op, | ||
216 | + MeterFailReason.EXISTING_METER); | ||
217 | + break; | ||
218 | + case INVALID_METER: | ||
219 | + providerService.meterOperationFailed(op, | ||
220 | + MeterFailReason.INVALID_METER); | ||
221 | + break; | ||
222 | + case UNKNOWN_METER: | ||
223 | + providerService.meterOperationFailed(op, | ||
224 | + MeterFailReason.UNKNOWN); | ||
225 | + break; | ||
226 | + case BAD_COMMAND: | ||
227 | + providerService.meterOperationFailed(op, | ||
228 | + MeterFailReason.UNKNOWN_COMMAND); | ||
229 | + break; | ||
230 | + case BAD_FLAGS: | ||
231 | + providerService.meterOperationFailed(op, | ||
232 | + MeterFailReason.UNKNOWN_FLAGS); | ||
233 | + break; | ||
234 | + case BAD_RATE: | ||
235 | + providerService.meterOperationFailed(op, | ||
236 | + MeterFailReason.BAD_RATE); | ||
237 | + break; | ||
238 | + case BAD_BURST: | ||
239 | + providerService.meterOperationFailed(op, | ||
240 | + MeterFailReason.BAD_BURST); | ||
241 | + break; | ||
242 | + case BAD_BAND: | ||
243 | + providerService.meterOperationFailed(op, | ||
244 | + MeterFailReason.BAD_BAND); | ||
245 | + break; | ||
246 | + case BAD_BAND_VALUE: | ||
247 | + providerService.meterOperationFailed(op, | ||
248 | + MeterFailReason.BAD_BAND_VALUE); | ||
249 | + break; | ||
250 | + case OUT_OF_METERS: | ||
251 | + providerService.meterOperationFailed(op, | ||
252 | + MeterFailReason.OUT_OF_METERS); | ||
253 | + break; | ||
254 | + case OUT_OF_BANDS: | ||
255 | + providerService.meterOperationFailed(op, | ||
256 | + MeterFailReason.OUT_OF_BANDS); | ||
257 | + break; | ||
258 | + default: | ||
259 | + providerService.meterOperationFailed(op, | ||
260 | + MeterFailReason.UNKNOWN); | ||
261 | + } | ||
262 | + } | ||
263 | + | ||
264 | + private class InternalMeterListener | ||
265 | + implements OpenFlowSwitchListener, OpenFlowEventListener { | ||
266 | + @Override | ||
267 | + public void handleMessage(Dpid dpid, OFMessage msg) { | ||
268 | + switch (msg.getType()) { | ||
269 | + case STATS_REPLY: | ||
270 | + pushMeterStats(dpid, (OFStatsReply) msg); | ||
271 | + break; | ||
272 | + case ERROR: | ||
273 | + OFErrorMsg error = (OFErrorMsg) msg; | ||
274 | + if (error.getErrType() == OFErrorType.METER_MOD_FAILED) { | ||
275 | + MeterOperation op = | ||
276 | + pendingOperations.getIfPresent(error.getXid()); | ||
277 | + pendingOperations.invalidate(error.getXid()); | ||
278 | + if (op == null) { | ||
279 | + log.warn("Unknown Meter operation failed {}", error); | ||
280 | + } else { | ||
281 | + OFMeterModFailedErrorMsg meterError = | ||
282 | + (OFMeterModFailedErrorMsg) error; | ||
283 | + signalMeterError(meterError, op); | ||
284 | + } | ||
285 | + } | ||
286 | + break; | ||
287 | + default: | ||
288 | + break; | ||
289 | + } | ||
290 | + | ||
291 | + } | ||
292 | + | ||
293 | + @Override | ||
294 | + public void switchAdded(Dpid dpid) { | ||
295 | + createStatsCollection(controller.getSwitch(dpid)); | ||
296 | + } | ||
297 | + | ||
298 | + @Override | ||
299 | + public void switchRemoved(Dpid dpid) { | ||
300 | + MeterStatsCollector msc = collectors.remove(dpid); | ||
301 | + if (msc != null) { | ||
302 | + msc.stop(); | ||
303 | + } | ||
304 | + } | ||
305 | + | ||
306 | + @Override | ||
307 | + public void switchChanged(Dpid dpid) { | ||
308 | + | ||
309 | + } | ||
310 | + | ||
311 | + @Override | ||
312 | + public void portChanged(Dpid dpid, OFPortStatus status) { | ||
313 | + | ||
314 | + } | ||
315 | + | ||
316 | + @Override | ||
317 | + public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) { | ||
318 | + | ||
319 | + } | ||
320 | + } | ||
321 | + | ||
322 | + | ||
323 | + | ||
61 | } | 324 | } | ... | ... |
-
Please register or login to post a comment