alshabib
Committed by Gerrit Code Review

OpenFlow Meter Provider - still need to parse meter stats

Change-Id: I4b313ea003b3801f81ec7d4823bf69de37fd8643
...@@ -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 }
......
...@@ -41,7 +41,7 @@ public final class MeterId { ...@@ -41,7 +41,7 @@ public final class MeterId {
41 * 41 *
42 * @return an integer 42 * @return an integer
43 */ 43 */
44 - int id() { 44 + public int id() {
45 return id; 45 return id;
46 } 46 }
47 47
......
...@@ -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>
......
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 +}