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 | + } | ||
| 182 | + | ||
| 183 | + } | ||
| 59 | 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); | ||
| 60 | } | 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