sangho
Committed by Gerrit Code Review

ONOS-894 : Implemented GroupProvider

Change-Id: I2755abd433921a420ad545fcf6fef61e90a8b89f
...@@ -149,7 +149,7 @@ ...@@ -149,7 +149,7 @@
149 <bundle>mvn:org.onosproject/onos-of-provider-device/@ONOS-VERSION</bundle> 149 <bundle>mvn:org.onosproject/onos-of-provider-device/@ONOS-VERSION</bundle>
150 <bundle>mvn:org.onosproject/onos-of-provider-packet/@ONOS-VERSION</bundle> 150 <bundle>mvn:org.onosproject/onos-of-provider-packet/@ONOS-VERSION</bundle>
151 <bundle>mvn:org.onosproject/onos-of-provider-flow/@ONOS-VERSION</bundle> 151 <bundle>mvn:org.onosproject/onos-of-provider-flow/@ONOS-VERSION</bundle>
152 - 152 + <bundle>mvn:org.onosproject/onos-of-provider-group/@ONOS-VERSION</bundle>
153 </feature> 153 </feature>
154 154
155 <feature name="onos-app-tvue" version="@FEATURE-VERSION" 155 <feature name="onos-app-tvue" version="@FEATURE-VERSION"
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<project xmlns="http://maven.apache.org/POM/4.0.0"
18 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 + <modelVersion>4.0.0</modelVersion>
21 +
22 + <parent>
23 + <groupId>org.onosproject</groupId>
24 + <artifactId>onos-of-providers</artifactId>
25 + <version>1.1.0-SNAPSHOT</version>
26 + <relativePath>../pom.xml</relativePath>
27 + </parent>
28 +
29 + <artifactId>onos-of-provider-group</artifactId>
30 + <packaging>bundle</packaging>
31 +
32 + <description>ONOS OpenFlow protocol group provider</description>
33 +
34 +</project>
...\ No newline at end of file ...\ No newline at end of file
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.group.impl;
17 +
18 +import com.google.common.collect.Lists;
19 +import org.onlab.packet.Ip4Address;
20 +import org.onlab.packet.MacAddress;
21 +import org.onlab.packet.VlanId;
22 +import org.onosproject.core.DefaultGroupId;
23 +import org.onosproject.core.GroupId;
24 +import org.onosproject.net.PortNumber;
25 +import org.onosproject.net.flow.DefaultTrafficTreatment;
26 +import org.onosproject.net.flow.TrafficTreatment;
27 +import org.onosproject.net.group.DefaultGroupBucket;
28 +import org.onosproject.net.group.GroupBucket;
29 +import org.onosproject.net.group.GroupBuckets;
30 +import org.projectfloodlight.openflow.protocol.OFBucket;
31 +import org.projectfloodlight.openflow.protocol.OFGroupType;
32 +import org.projectfloodlight.openflow.protocol.action.OFAction;
33 +import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
34 +import org.projectfloodlight.openflow.protocol.action.OFActionCopyTtlIn;
35 +import org.projectfloodlight.openflow.protocol.action.OFActionCopyTtlOut;
36 +import org.projectfloodlight.openflow.protocol.action.OFActionDecMplsTtl;
37 +import org.projectfloodlight.openflow.protocol.action.OFActionDecNwTtl;
38 +import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
39 +import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
40 +import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls;
41 +import org.projectfloodlight.openflow.protocol.action.OFActionPushMpls;
42 +import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
43 +import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
44 +import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
45 +import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
46 +import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
47 +import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
48 +import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
49 +import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
50 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
51 +import org.projectfloodlight.openflow.types.IPv4Address;
52 +import org.projectfloodlight.openflow.types.OFVlanVidMatch;
53 +import org.projectfloodlight.openflow.types.U32;
54 +import org.projectfloodlight.openflow.types.VlanPcp;
55 +import org.slf4j.Logger;
56 +
57 +import java.util.List;
58 +
59 +import static org.slf4j.LoggerFactory.getLogger;
60 +
61 +/*
62 + * Builder for GroupBucketEntry.
63 + */
64 +public class GroupBucketEntryBuilder {
65 +
66 + private List<OFBucket> ofBuckets;
67 + private OFGroupType type;
68 +
69 + private final Logger log = getLogger(getClass());
70 +
71 + /**
72 + * Creates a builder.
73 + *
74 + * @param ofBuckets list of OFBucket
75 + * @param type Group type
76 + */
77 + public GroupBucketEntryBuilder(List<OFBucket> ofBuckets, OFGroupType type) {
78 + this.ofBuckets = ofBuckets;
79 + this.type = type;
80 + }
81 +
82 + /**
83 + * Builds a GroupBuckets.
84 + *
85 + * @return GroupBuckets object, a list of GroupBuck
86 + */
87 + public GroupBuckets build() {
88 + List<GroupBucket> bucketList = Lists.newArrayList();
89 +
90 + for (OFBucket bucket: ofBuckets) {
91 + TrafficTreatment treatment = buildTreatment(bucket.getActions());
92 + // TODO: Use GroupBucketEntry
93 + GroupBucket groupBucket = null;
94 + switch (type) {
95 + case INDIRECT:
96 + groupBucket =
97 + DefaultGroupBucket.createIndirectGroupBucket(treatment);
98 + break;
99 + case SELECT:
100 + groupBucket =
101 + DefaultGroupBucket.createSelectGroupBucket(treatment);
102 + break;
103 + case FF:
104 + PortNumber port =
105 + PortNumber.portNumber(bucket.getWatchPort().getPortNumber());
106 + GroupId groupId =
107 + new DefaultGroupId(bucket.getWatchGroup().getGroupNumber());
108 + groupBucket =
109 + DefaultGroupBucket.createFailoverGroupBucket(treatment,
110 + port, groupId);
111 + break;
112 + default:
113 + log.error("Unsupported Group type : {}", type);
114 + }
115 + if (groupBucket != null) {
116 + bucketList.add(groupBucket);
117 + }
118 + }
119 + return new GroupBuckets(bucketList);
120 + }
121 +
122 +
123 + private TrafficTreatment buildTreatment(List<OFAction> actions) {
124 + TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
125 + // If this is a drop rule
126 + if (actions.size() == 0) {
127 + builder.drop();
128 + return builder.build();
129 + }
130 + for (OFAction act : actions) {
131 + switch (act.getType()) {
132 + case OUTPUT:
133 + OFActionOutput out = (OFActionOutput) act;
134 + builder.setOutput(
135 + PortNumber.portNumber(out.getPort().getPortNumber()));
136 + break;
137 + case SET_VLAN_VID:
138 + OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
139 + builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
140 + break;
141 + case SET_VLAN_PCP:
142 + OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
143 + builder.setVlanPcp(pcp.getVlanPcp().getValue());
144 + break;
145 + case SET_DL_DST:
146 + OFActionSetDlDst dldst = (OFActionSetDlDst) act;
147 + builder.setEthDst(
148 + MacAddress.valueOf(dldst.getDlAddr().getLong()));
149 + break;
150 + case SET_DL_SRC:
151 + OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
152 + builder.setEthSrc(
153 + MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
154 +
155 + break;
156 + case SET_NW_DST:
157 + OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
158 + IPv4Address di = nwdst.getNwAddr();
159 + builder.setIpDst(Ip4Address.valueOf(di.getInt()));
160 + break;
161 + case SET_NW_SRC:
162 + OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
163 + IPv4Address si = nwsrc.getNwAddr();
164 + builder.setIpSrc(Ip4Address.valueOf(si.getInt()));
165 + break;
166 + case EXPERIMENTER:
167 + OFActionExperimenter exp = (OFActionExperimenter) act;
168 + if (exp.getExperimenter() == 0x80005A06 ||
169 + exp.getExperimenter() == 0x748771) {
170 + OFActionCircuit ct = (OFActionCircuit) exp;
171 + builder.setLambda(((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber());
172 + } else {
173 + log.warn("Unsupported OFActionExperimenter {}", exp.getExperimenter());
174 + }
175 + break;
176 + case SET_FIELD:
177 + OFActionSetField setField = (OFActionSetField) act;
178 + handleSetField(builder, setField.getField());
179 + break;
180 + case POP_MPLS:
181 + OFActionPopMpls popMpls = (OFActionPopMpls) act;
182 + builder.popMpls((short) popMpls.getEthertype().getValue());
183 + break;
184 + case PUSH_MPLS:
185 + OFActionPushMpls pushMpls = (OFActionPushMpls) act;
186 + builder.pushMpls();
187 + break;
188 + case COPY_TTL_IN:
189 + OFActionCopyTtlIn copyTtlIn = (OFActionCopyTtlIn) act;
190 + builder.copyTtlIn();
191 + break;
192 + case COPY_TTL_OUT:
193 + OFActionCopyTtlOut copyTtlOut = (OFActionCopyTtlOut) act;
194 + builder.copyTtlOut();
195 + break;
196 + case DEC_MPLS_TTL:
197 + OFActionDecMplsTtl decMplsTtl = (OFActionDecMplsTtl) act;
198 + builder.decMplsTtl();
199 + break;
200 + case DEC_NW_TTL:
201 + OFActionDecNwTtl decNwTtl = (OFActionDecNwTtl) act;
202 + builder.decNwTtl();
203 + break;
204 + case SET_TP_DST:
205 + case SET_TP_SRC:
206 + case POP_PBB:
207 + case POP_VLAN:
208 + case PUSH_PBB:
209 + case PUSH_VLAN:
210 + case SET_MPLS_LABEL:
211 + case SET_MPLS_TC:
212 + case SET_MPLS_TTL:
213 + case SET_NW_ECN:
214 + case SET_NW_TOS:
215 + case SET_NW_TTL:
216 + case SET_QUEUE:
217 + case STRIP_VLAN:
218 + case ENQUEUE:
219 +
220 + case GROUP:
221 + default:
222 + log.warn("Action type {} not yet implemented.", act.getType());
223 + }
224 + }
225 +
226 + return builder.build();
227 + }
228 +
229 + private void handleSetField(TrafficTreatment.Builder builder, OFOxm<?> oxm) {
230 + switch (oxm.getMatchField().id) {
231 + case VLAN_PCP:
232 + @SuppressWarnings("unchecked")
233 + OFOxm<VlanPcp> vlanpcp = (OFOxm<VlanPcp>) oxm;
234 + builder.setVlanPcp(vlanpcp.getValue().getValue());
235 + break;
236 + case VLAN_VID:
237 + @SuppressWarnings("unchecked")
238 + OFOxm<OFVlanVidMatch> vlanvid = (OFOxm<OFVlanVidMatch>) oxm;
239 + builder.setVlanId(VlanId.vlanId(vlanvid.getValue().getVlan()));
240 + break;
241 + case ETH_DST:
242 + @SuppressWarnings("unchecked")
243 + OFOxm<org.projectfloodlight.openflow.types.MacAddress> ethdst =
244 + (OFOxm<org.projectfloodlight.openflow.types.MacAddress>) oxm;
245 + builder.setEthDst(MacAddress.valueOf(ethdst.getValue().getLong()));
246 + break;
247 + case ETH_SRC:
248 + @SuppressWarnings("unchecked")
249 + OFOxm<org.projectfloodlight.openflow.types.MacAddress> ethsrc =
250 + (OFOxm<org.projectfloodlight.openflow.types.MacAddress>) oxm;
251 + builder.setEthSrc(MacAddress.valueOf(ethsrc.getValue().getLong()));
252 + break;
253 + case IPV4_DST:
254 + @SuppressWarnings("unchecked")
255 + OFOxm<IPv4Address> ip4dst = (OFOxm<IPv4Address>) oxm;
256 + builder.setIpDst(Ip4Address.valueOf(ip4dst.getValue().getInt()));
257 + break;
258 + case IPV4_SRC:
259 + @SuppressWarnings("unchecked")
260 + OFOxm<IPv4Address> ip4src = (OFOxm<IPv4Address>) oxm;
261 + builder.setIpSrc(Ip4Address.valueOf(ip4src.getValue().getInt()));
262 + break;
263 + case MPLS_LABEL:
264 + @SuppressWarnings("unchecked")
265 + OFOxm<U32> labelId = (OFOxm<U32>) oxm;
266 + builder.setMpls((int) labelId.getValue().getValue());
267 + break;
268 + case ARP_OP:
269 + case ARP_SHA:
270 + case ARP_SPA:
271 + case ARP_THA:
272 + case ARP_TPA:
273 + case BSN_EGR_PORT_GROUP_ID:
274 + case BSN_GLOBAL_VRF_ALLOWED:
275 + case BSN_IN_PORTS_128:
276 + case BSN_L3_DST_CLASS_ID:
277 + case BSN_L3_INTERFACE_CLASS_ID:
278 + case BSN_L3_SRC_CLASS_ID:
279 + case BSN_LAG_ID:
280 + case BSN_TCP_FLAGS:
281 + case BSN_UDF0:
282 + case BSN_UDF1:
283 + case BSN_UDF2:
284 + case BSN_UDF3:
285 + case BSN_UDF4:
286 + case BSN_UDF5:
287 + case BSN_UDF6:
288 + case BSN_UDF7:
289 + case BSN_VLAN_XLATE_PORT_GROUP_ID:
290 + case BSN_VRF:
291 + case ETH_TYPE:
292 + case ICMPV4_CODE:
293 + case ICMPV4_TYPE:
294 + case ICMPV6_CODE:
295 + case ICMPV6_TYPE:
296 + case IN_PHY_PORT:
297 + case IN_PORT:
298 + case IPV6_DST:
299 + case IPV6_FLABEL:
300 + case IPV6_ND_SLL:
301 + case IPV6_ND_TARGET:
302 + case IPV6_ND_TLL:
303 + case IPV6_SRC:
304 + case IP_DSCP:
305 + case IP_ECN:
306 + case IP_PROTO:
307 + case METADATA:
308 + case MPLS_TC:
309 + case OCH_SIGID:
310 + case OCH_SIGID_BASIC:
311 + case OCH_SIGTYPE:
312 + case OCH_SIGTYPE_BASIC:
313 + case SCTP_DST:
314 + case SCTP_SRC:
315 + case TCP_DST:
316 + case TCP_SRC:
317 + case TUNNEL_ID:
318 + case UDP_DST:
319 + case UDP_SRC:
320 + default:
321 + log.warn("Set field type {} not yet implemented.", oxm.getMatchField().id);
322 + break;
323 + }
324 + }
325 +}
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.group.impl;
17 +
18 +import org.onlab.packet.Ip4Address;
19 +import org.onosproject.core.GroupId;
20 +import org.onosproject.net.PortNumber;
21 +import org.onosproject.net.flow.TrafficTreatment;
22 +import org.onosproject.net.flow.instructions.Instruction;
23 +import org.onosproject.net.flow.instructions.Instructions;
24 +import org.onosproject.net.flow.instructions.L0ModificationInstruction;
25 +import org.onosproject.net.flow.instructions.L2ModificationInstruction;
26 +import org.onosproject.net.flow.instructions.L3ModificationInstruction;
27 +import org.onosproject.net.group.GroupBucket;
28 +import org.onosproject.net.group.GroupBuckets;
29 +import org.onosproject.net.group.GroupDescription;
30 +import org.projectfloodlight.openflow.protocol.OFBucket;
31 +import org.projectfloodlight.openflow.protocol.OFFactory;
32 +import org.projectfloodlight.openflow.protocol.OFGroupAdd;
33 +import org.projectfloodlight.openflow.protocol.OFGroupDelete;
34 +import org.projectfloodlight.openflow.protocol.OFGroupMod;
35 +import org.projectfloodlight.openflow.protocol.OFGroupType;
36 +import org.projectfloodlight.openflow.protocol.action.OFAction;
37 +import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
38 +import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
39 +import org.projectfloodlight.openflow.types.CircuitSignalID;
40 +import org.projectfloodlight.openflow.types.EthType;
41 +import org.projectfloodlight.openflow.types.IPv4Address;
42 +import org.projectfloodlight.openflow.types.MacAddress;
43 +import org.projectfloodlight.openflow.types.OFGroup;
44 +import org.projectfloodlight.openflow.types.OFPort;
45 +import org.projectfloodlight.openflow.types.OFVlanVidMatch;
46 +import org.projectfloodlight.openflow.types.U32;
47 +import org.projectfloodlight.openflow.types.VlanPcp;
48 +import org.slf4j.Logger;
49 +
50 +import java.util.ArrayList;
51 +import java.util.LinkedList;
52 +import java.util.List;
53 +import java.util.Optional;
54 +
55 +import static org.slf4j.LoggerFactory.getLogger;
56 +
57 +/*
58 + * Builder for GroupMod.
59 + */
60 +public final class GroupModBuilder {
61 +
62 + private GroupBuckets buckets;
63 + private GroupId groupId;
64 + private GroupDescription.Type type;
65 + private OFFactory factory;
66 + private Long xid;
67 +
68 + private final Logger log = getLogger(getClass());
69 +
70 + private static final int OFPCML_NO_BUFFER = 0xffff;
71 +
72 + private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
73 + GroupDescription.Type type, OFFactory factory,
74 + Optional<Long> xid) {
75 + this.buckets = buckets;
76 + this.groupId = groupId;
77 + this.type = type;
78 + this.factory = factory;
79 + this.xid = xid.orElse((long) 0);
80 + }
81 +
82 + /**
83 + * Creates a builder for GroupMod.
84 + *
85 + * @param buckets GroupBuckets object
86 + * @param groupId Group Id to create
87 + * @param type Group type
88 + * @param factory OFFactory object
89 + * @param xid transaction ID
90 + * @return GroupModBuilder object
91 + */
92 + public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
93 + GroupDescription.Type type, OFFactory factory,
94 + Optional<Long> xid) {
95 +
96 + return new GroupModBuilder(buckets, groupId, type, factory, xid);
97 + }
98 +
99 + /**
100 + * Builds the GroupAdd OF message.
101 + *
102 + * @return GroupAdd OF message
103 + */
104 + public OFGroupAdd buildGroupAdd() {
105 +
106 + List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
107 + for (GroupBucket bucket: buckets.buckets()) {
108 + List<OFAction> actions = buildActions(bucket.treatment());
109 +
110 + OFBucket.Builder bucketBuilder = factory.buildBucket();
111 + bucketBuilder.setActions(actions);
112 + if (type == GroupDescription.Type.SELECT) {
113 + bucketBuilder.setWeight(1);
114 + }
115 + bucketBuilder.setWatchGroup(OFGroup.ANY);
116 + bucketBuilder.setWatchPort(OFPort.ANY);
117 + OFBucket ofBucket = bucketBuilder.build();
118 + ofBuckets.add(ofBucket);
119 + }
120 +
121 + OFGroupAdd groupMsg = factory.buildGroupAdd()
122 + .setGroup(OFGroup.of(groupId.id()))
123 + .setBuckets(ofBuckets)
124 + .setGroupType(getOFGroupType(type))
125 + .setXid(xid)
126 + .build();
127 +
128 + return groupMsg;
129 + }
130 +
131 + /**
132 + * Builds the GroupMod OF message.
133 + *
134 + * @return GroupMod OF message
135 + */
136 + public OFGroupMod buildGroupMod() {
137 + List<OFBucket> ofBuckets = new ArrayList<OFBucket>();
138 + for (GroupBucket bucket: buckets.buckets()) {
139 + List<OFAction> actions = buildActions(bucket.treatment());
140 +
141 + OFBucket.Builder bucketBuilder = factory.buildBucket();
142 + bucketBuilder.setActions(actions);
143 + if (type == GroupDescription.Type.SELECT) {
144 + bucketBuilder.setWeight(1);
145 + }
146 + bucketBuilder.setWatchGroup(OFGroup.ANY);
147 + bucketBuilder.setWatchPort(OFPort.ANY);
148 + OFBucket ofBucket = bucketBuilder.build();
149 + ofBuckets.add(ofBucket);
150 + }
151 +
152 + OFGroupMod groupMsg = factory.buildGroupModify()
153 + .setGroup(OFGroup.of(groupId.id()))
154 + .setBuckets(ofBuckets)
155 + .setGroupType(getOFGroupType(type))
156 + .setXid(xid)
157 + .build();
158 +
159 + return groupMsg;
160 + }
161 +
162 + /**
163 + * Builds the GroupDel OF message.
164 + *
165 + * @return GroupDel OF message
166 + */
167 + public OFGroupDelete buildGroupDel() {
168 +
169 + OFGroupDelete groupMsg = factory.buildGroupDelete()
170 + .setGroup(OFGroup.of(groupId.id()))
171 + .setGroupType(OFGroupType.SELECT)
172 + .setXid(xid)
173 + .build();
174 +
175 + return groupMsg;
176 + }
177 +
178 + private List<OFAction> buildActions(TrafficTreatment treatment) {
179 + List<OFAction> actions = new LinkedList<>();
180 + if (treatment == null) {
181 + return actions;
182 + }
183 + for (Instruction i : treatment.instructions()) {
184 + switch (i.type()) {
185 + case DROP:
186 + log.warn("Saw drop action; assigning drop action");
187 + return new LinkedList<>();
188 + case L0MODIFICATION:
189 + actions.add(buildL0Modification(i));
190 + break;
191 + case L2MODIFICATION:
192 + actions.add(buildL2Modification(i));
193 + break;
194 + case L3MODIFICATION:
195 + actions.add(buildL3Modification(i));
196 + break;
197 + case OUTPUT:
198 + Instructions.OutputInstruction out =
199 + (Instructions.OutputInstruction) i;
200 + OFActionOutput.Builder action = factory.actions().buildOutput()
201 + .setPort(OFPort.of((int) out.port().toLong()));
202 + if (out.port().equals(PortNumber.CONTROLLER)) {
203 + action.setMaxLen(OFPCML_NO_BUFFER);
204 + }
205 + actions.add(action.build());
206 + break;
207 + case GROUP:
208 + default:
209 + log.warn("Instruction type {} not yet implemented.", i.type());
210 + }
211 + }
212 +
213 + return actions;
214 + }
215 +
216 + private OFAction buildL0Modification(Instruction i) {
217 + L0ModificationInstruction l0m = (L0ModificationInstruction) i;
218 + switch (l0m.subtype()) {
219 + case LAMBDA:
220 + L0ModificationInstruction.ModLambdaInstruction ml =
221 + (L0ModificationInstruction.ModLambdaInstruction) i;
222 + return factory.actions().circuit(factory.oxms().ochSigidBasic(
223 + new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
224 + default:
225 + log.warn("Unimplemented action type {}.", l0m.subtype());
226 + break;
227 + }
228 + return null;
229 + }
230 +
231 + private OFAction buildL2Modification(Instruction i) {
232 + L2ModificationInstruction l2m = (L2ModificationInstruction) i;
233 + L2ModificationInstruction.ModEtherInstruction eth;
234 + OFOxm<?> oxm = null;
235 + switch (l2m.subtype()) {
236 + case ETH_DST:
237 + eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
238 + oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
239 + break;
240 + case ETH_SRC:
241 + eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
242 + oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
243 + break;
244 + case VLAN_ID:
245 + L2ModificationInstruction.ModVlanIdInstruction vlanId =
246 + (L2ModificationInstruction.ModVlanIdInstruction) l2m;
247 + oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
248 + break;
249 + case VLAN_PCP:
250 + L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
251 + (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
252 + oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
253 + break;
254 + case MPLS_PUSH:
255 + L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
256 + (L2ModificationInstruction.PushHeaderInstructions) l2m;
257 + return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
258 + .ethernetType().getEtherType()));
259 + case MPLS_POP:
260 + L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
261 + (L2ModificationInstruction.PushHeaderInstructions) l2m;
262 + return factory.actions().popMpls(EthType.of(popHeaderInstructions
263 + .ethernetType().getEtherType()));
264 + case MPLS_LABEL:
265 + L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
266 + (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
267 + oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label()
268 + .longValue()));
269 + break;
270 + case DEC_MPLS_TTL:
271 + return factory.actions().decMplsTtl();
272 + default:
273 + log.warn("Unimplemented action type {}.", l2m.subtype());
274 + break;
275 + }
276 +
277 + if (oxm != null) {
278 + return factory.actions().buildSetField().setField(oxm).build();
279 + }
280 + return null;
281 + }
282 +
283 + private OFAction buildL3Modification(Instruction i) {
284 + L3ModificationInstruction l3m = (L3ModificationInstruction) i;
285 + L3ModificationInstruction.ModIPInstruction ip;
286 + Ip4Address ip4;
287 + OFOxm<?> oxm = null;
288 + switch (l3m.subtype()) {
289 + case IP_DST:
290 + ip = (L3ModificationInstruction.ModIPInstruction) i;
291 + ip4 = ip.ip().getIp4Address();
292 + oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
293 + break;
294 + case IP_SRC:
295 + ip = (L3ModificationInstruction.ModIPInstruction) i;
296 + ip4 = ip.ip().getIp4Address();
297 + oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
298 + break;
299 + case DEC_TTL:
300 + return factory.actions().decNwTtl();
301 + case TTL_IN:
302 + return factory.actions().copyTtlIn();
303 + case TTL_OUT:
304 + return factory.actions().copyTtlOut();
305 + default:
306 + log.warn("Unimplemented action type {}.", l3m.subtype());
307 + break;
308 + }
309 +
310 + if (oxm != null) {
311 + return factory.actions().buildSetField().setField(oxm).build();
312 + }
313 + return null;
314 + }
315 +
316 + private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
317 + switch (groupType) {
318 + case INDIRECT:
319 + return OFGroupType.INDIRECT;
320 + case SELECT:
321 + return OFGroupType.SELECT;
322 + case FAILOVER:
323 + return OFGroupType.FF;
324 + case ALL:
325 + return OFGroupType.ALL;
326 + default:
327 + log.error("Unsupported group type : {}", groupType);
328 + break;
329 + }
330 + return null;
331 + }
332 +}
333 +
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.group.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.OFGroupDescStatsRequest;
26 +import org.projectfloodlight.openflow.protocol.OFGroupStatsRequest;
27 +import org.projectfloodlight.openflow.types.OFGroup;
28 +import org.slf4j.Logger;
29 +
30 +import java.util.concurrent.TimeUnit;
31 +import java.util.concurrent.atomic.AtomicLong;
32 +
33 +import static org.slf4j.LoggerFactory.getLogger;
34 +
35 +/*
36 + * Sends Group Stats Request and collect the group statistics with a time interval.
37 + */
38 +public class GroupStatsCollector implements TimerTask {
39 +
40 + private final HashedWheelTimer timer = Timer.getTimer();
41 + private final OpenFlowSwitch sw;
42 + private final Logger log = getLogger(getClass());
43 + private final int refreshInterval;
44 +
45 + private Timeout timeout;
46 + private final AtomicLong xidCounter = new AtomicLong(1);
47 +
48 + private boolean stopTimer = false;
49 +
50 + /**
51 + * Creates a GroupStatsCollector object.
52 + *
53 + * @param sw Open Flow switch
54 + * @param interval time interval for collecting group statistic
55 + */
56 + public GroupStatsCollector(OpenFlowSwitch sw, int interval) {
57 + this.sw = sw;
58 + this.refreshInterval = interval;
59 + }
60 +
61 + @Override
62 + public void run(Timeout timeout) throws Exception {
63 + log.trace("Collecting stats for {}", sw.getStringId());
64 +
65 + sendGroupStatistic();
66 +
67 + if (!this.stopTimer) {
68 + log.trace("Scheduling stats collection in {} seconds for {}",
69 + this.refreshInterval, this.sw.getStringId());
70 + timeout.getTimer().newTimeout(this, refreshInterval,
71 + TimeUnit.SECONDS);
72 + }
73 + }
74 +
75 + private void sendGroupStatistic() {
76 + if (log.isTraceEnabled()) {
77 + log.trace("sendGroupStatistics {}:{}", sw.getStringId(), sw.getRole());
78 + }
79 + if (sw.getRole() != RoleState.MASTER) {
80 + return;
81 + }
82 + Long statsXid = xidCounter.getAndAdd(2);
83 + OFGroupStatsRequest statsRequest = sw.factory().buildGroupStatsRequest()
84 + .setGroup(OFGroup.ALL)
85 + .setXid(statsXid)
86 + .build();
87 + sw.sendMsg(statsRequest);
88 +
89 + Long descXid = statsXid + 1;
90 + OFGroupDescStatsRequest descStatsRequest =
91 + sw.factory().buildGroupDescStatsRequest()
92 + .setXid(descXid)
93 + .build();
94 + sw.sendMsg(descStatsRequest);
95 + }
96 +
97 + /**
98 + * Starts the collector.
99 + */
100 + public void start() {
101 + log.info("Staring Group Stats collection thread for {}", sw.getStringId());
102 + timeout = timer.newTimeout(this, 1, TimeUnit.SECONDS);
103 + }
104 +
105 + /**
106 + * Stops the collector.
107 + */
108 + public void stop() {
109 + log.info("Stopping Group Stats collection thread for {}", sw.getStringId());
110 + this.stopTimer = true;
111 + timeout.cancel();
112 + }
113 +}
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.group.impl;
18 +
19 +import com.google.common.collect.Maps;
20 +import org.apache.felix.scr.annotations.Activate;
21 +import org.apache.felix.scr.annotations.Component;
22 +import org.apache.felix.scr.annotations.Deactivate;
23 +import org.apache.felix.scr.annotations.Reference;
24 +import org.apache.felix.scr.annotations.ReferenceCardinality;
25 +import org.onosproject.core.DefaultGroupId;
26 +import org.onosproject.core.GroupId;
27 +import org.onosproject.net.DeviceId;
28 +import org.onosproject.net.group.DefaultGroup;
29 +import org.onosproject.net.group.Group;
30 +import org.onosproject.net.group.GroupBuckets;
31 +import org.onosproject.net.group.GroupDescription;
32 +import org.onosproject.net.group.GroupOperation;
33 +import org.onosproject.net.group.GroupOperations;
34 +import org.onosproject.net.group.GroupProvider;
35 +import org.onosproject.net.group.GroupProviderRegistry;
36 +import org.onosproject.net.group.GroupProviderService;
37 +import org.onosproject.net.provider.AbstractProvider;
38 +import org.onosproject.net.provider.ProviderId;
39 +import org.onosproject.openflow.controller.Dpid;
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.OFGroupDescStatsEntry;
48 +import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
49 +import org.projectfloodlight.openflow.protocol.OFGroupMod;
50 +import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry;
51 +import org.projectfloodlight.openflow.protocol.OFGroupStatsReply;
52 +import org.projectfloodlight.openflow.protocol.OFGroupType;
53 +import org.projectfloodlight.openflow.protocol.OFMessage;
54 +import org.projectfloodlight.openflow.protocol.OFPortStatus;
55 +import org.projectfloodlight.openflow.protocol.OFStatsReply;
56 +import org.projectfloodlight.openflow.protocol.OFStatsType;
57 +import org.slf4j.Logger;
58 +
59 +import java.util.Collection;
60 +import java.util.Map;
61 +import java.util.Optional;
62 +import java.util.concurrent.atomic.AtomicLong;
63 +
64 +import static org.slf4j.LoggerFactory.getLogger;
65 +
66 +/**
67 + * Provider which uses an OpenFlow controller to handle Group.
68 + */
69 +@Component(immediate = true)
70 +public class OpenFlowGroupProvider extends AbstractProvider implements GroupProvider {
71 +
72 + private final Logger log = getLogger(getClass());
73 +
74 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 + protected OpenFlowController controller;
76 +
77 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 + protected GroupProviderRegistry providerRegistry;
79 +
80 + private GroupProviderService providerService;
81 +
82 + static final int POLL_INTERVAL = 10;
83 +
84 + private final InternalGroupProvider listener = new InternalGroupProvider();
85 +
86 + private final AtomicLong xidCounter = new AtomicLong(1);
87 + private final Map<Dpid, GroupStatsCollector> collectors = Maps.newHashMap();
88 + private final Map<Long, OFStatsReply> groupStats = Maps.newHashMap();
89 + private final Map<Long, GroupOperation> pendingGroupOperations =
90 + Maps.newConcurrentMap();
91 +
92 + /**
93 + * Creates a OpenFlow group provider.
94 + */
95 + public OpenFlowGroupProvider() {
96 + super(new ProviderId("of", "org.onosproject.provider.group"));
97 + }
98 +
99 + @Activate
100 + public void activate() {
101 + providerService = providerRegistry.register(this);
102 + controller.addListener(listener);
103 + controller.addEventListener(listener);
104 +
105 + for (OpenFlowSwitch sw : controller.getSwitches()) {
106 + GroupStatsCollector gsc = new GroupStatsCollector(sw, POLL_INTERVAL);
107 + gsc.start();
108 + collectors.put(new Dpid(sw.getId()), gsc);
109 + }
110 +
111 + log.info("Started");
112 + }
113 +
114 + @Deactivate
115 + public void deactivate() {
116 + providerRegistry.unregister(this);
117 + providerService = null;
118 +
119 + log.info("Stopped");
120 + }
121 +
122 + @Override
123 + public void performGroupOperation(DeviceId deviceId, GroupOperations groupOps) {
124 + Map<OFGroupMod, OpenFlowSwitch> mods = Maps.newIdentityHashMap();
125 + final Dpid dpid = Dpid.dpid(deviceId.uri());
126 + OpenFlowSwitch sw = controller.getSwitch(dpid);
127 + for (GroupOperation groupOperation: groupOps.operations()) {
128 + if (sw == null) {
129 + log.error("SW {} is not found", sw.getStringId());
130 + return;
131 + }
132 + final Long groupModXid = xidCounter.getAndIncrement();
133 + GroupModBuilder builder =
134 + GroupModBuilder.builder(groupOperation.buckets(),
135 + groupOperation.groupId(),
136 + groupOperation.groupType(),
137 + sw.factory(),
138 + Optional.of(groupModXid));
139 + OFGroupMod groupMod = null;
140 + switch (groupOperation.opType()) {
141 + case ADD:
142 + groupMod = builder.buildGroupAdd();
143 + break;
144 + case MODIFY:
145 + groupMod = builder.buildGroupMod();
146 + break;
147 + case DELETE:
148 + groupMod = builder.buildGroupDel();
149 + break;
150 + default:
151 + log.error("Unsupported Group operation");
152 + }
153 + sw.sendMsg(groupMod);
154 + pendingGroupOperations.put(groupModXid, groupOperation);
155 + }
156 + }
157 +
158 + private void pushGroupMetrics(Dpid dpid, OFStatsReply statsReply) {
159 + DeviceId deviceId = DeviceId.deviceId(Dpid.uri(dpid));
160 +
161 + OFGroupStatsReply groupStatsReply = null;
162 + OFGroupDescStatsReply groupDescStatsReply = null;
163 +
164 + if (statsReply.getStatsType() == OFStatsType.GROUP) {
165 + OFStatsReply reply = groupStats.get(statsReply.getXid() + 1);
166 + if (reply != null) {
167 + groupStatsReply = (OFGroupStatsReply) statsReply;
168 + groupDescStatsReply = (OFGroupDescStatsReply) reply;
169 + groupStats.remove(statsReply.getXid() + 1);
170 + } else {
171 + groupStats.put(statsReply.getXid(), statsReply);
172 + }
173 + } else if (statsReply.getStatsType() == OFStatsType.GROUP_DESC) {
174 + OFStatsReply reply = groupStats.get(statsReply.getXid() - 1);
175 + if (reply != null) {
176 + groupStatsReply = (OFGroupStatsReply) reply;
177 + groupDescStatsReply = (OFGroupDescStatsReply) statsReply;
178 + groupStats.remove(statsReply.getXid() - 1);
179 + } else {
180 + groupStats.put(statsReply.getXid(), statsReply);
181 + }
182 + }
183 +
184 + if (groupStatsReply != null && groupDescStatsReply != null) {
185 + Collection<Group> groups = buildGroupMetrics(deviceId,
186 + groupStatsReply, groupDescStatsReply);
187 + providerService.pushGroupMetrics(deviceId, groups);
188 + for (Group group: groups) {
189 + pendingGroupOperations.remove(group.id());
190 + }
191 + }
192 + }
193 +
194 + private Collection<Group> buildGroupMetrics(DeviceId deviceId,
195 + OFGroupStatsReply groupStatsReply,
196 + OFGroupDescStatsReply groupDescStatsReply) {
197 +
198 + Map<Integer, Group> groups = Maps.newHashMap();
199 +
200 + for (OFGroupDescStatsEntry entry: groupDescStatsReply.getEntries()) {
201 + int id = entry.getGroup().getGroupNumber();
202 + GroupId groupId = new DefaultGroupId(id);
203 + GroupDescription.Type type = getGroupType(entry.getGroupType());
204 + GroupBuckets buckets = new GroupBucketEntryBuilder(entry.getBuckets(),
205 + entry.getGroupType()).build();
206 + DefaultGroup group = new DefaultGroup(groupId, deviceId, type, buckets);
207 + groups.put(id, group);
208 + }
209 +
210 + for (OFGroupStatsEntry entry: groupStatsReply.getEntries()) {
211 + int groupId = entry.getGroup().getGroupNumber();
212 + DefaultGroup group = (DefaultGroup) groups.get(groupId);
213 + if (group != null) {
214 + group.setBytes(entry.getByteCount().getValue());
215 + group.setLife(entry.getDurationSec());
216 + group.setPackets(entry.getPacketCount().getValue());
217 + group.setReferenceCount(entry.getRefCount());
218 + }
219 + }
220 +
221 + return groups.values();
222 + }
223 +
224 + private GroupDescription.Type getGroupType(OFGroupType type) {
225 + switch (type) {
226 + case ALL:
227 + return GroupDescription.Type.ALL;
228 + case INDIRECT:
229 + return GroupDescription.Type.INDIRECT;
230 + case SELECT:
231 + return GroupDescription.Type.SELECT;
232 + case FF:
233 + return GroupDescription.Type.FAILOVER;
234 + default:
235 + log.error("Unsupported OF group type : {}", type);
236 + break;
237 + }
238 + return null;
239 + }
240 +
241 + private class InternalGroupProvider
242 + implements OpenFlowSwitchListener, OpenFlowEventListener {
243 +
244 + @Override
245 + public void handleMessage(Dpid dpid, OFMessage msg) {
246 + switch (msg.getType()) {
247 + case STATS_REPLY:
248 + pushGroupMetrics(dpid, (OFStatsReply) msg);
249 + break;
250 + case ERROR:
251 + OFErrorMsg errorMsg = (OFErrorMsg) msg;
252 + if (errorMsg.getErrType() == OFErrorType.GROUP_MOD_FAILED) {
253 + GroupOperation operation =
254 + pendingGroupOperations.get(errorMsg.getXid());
255 + if (operation != null) {
256 + providerService.groupOperationFailed(operation);
257 + log.warn("received Error message {} from {}", msg, dpid);
258 + }
259 + break;
260 + }
261 + default:
262 + log.debug("Unhandled message type: {}", msg.getType());
263 + }
264 + }
265 +
266 + @Override
267 + public void switchAdded(Dpid dpid) {
268 + GroupStatsCollector gsc = new GroupStatsCollector(
269 + controller.getSwitch(dpid), POLL_INTERVAL);
270 + gsc.start();
271 + collectors.put(dpid, gsc);
272 + }
273 +
274 + @Override
275 + public void switchRemoved(Dpid dpid) {
276 + GroupStatsCollector collector = collectors.remove(dpid);
277 + if (collector != null) {
278 + collector.stop();
279 + }
280 + }
281 +
282 + @Override
283 + public void switchChanged(Dpid dpid) {
284 + }
285 +
286 + @Override
287 + public void portChanged(Dpid dpid, OFPortStatus status) {
288 + }
289 +
290 + @Override
291 + public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
292 + }
293 + }
294 +
295 +}
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
37 <module>host</module> 37 <module>host</module>
38 <module>packet</module> 38 <module>packet</module>
39 <module>flow</module> 39 <module>flow</module>
40 + <module>group</module>
40 </modules> 41 </modules>
41 42
42 <dependencies> 43 <dependencies>
......