blob: 016b0cf3a9c8a05fd15b7a28162687da32fe1b1f [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.of.flow.impl;
alshabibeec3a062014-09-17 18:01:26 -070017
Jonathan Hart6cd2f352015-01-13 17:44:45 -080018import org.onlab.packet.Ip4Address;
19import org.onlab.packet.Ip4Prefix;
Charles M.C. Chan52fae7d2015-01-17 00:35:53 +080020import org.onlab.packet.Ip6Address;
21import org.onlab.packet.Ip6Prefix;
Jonathan Hart6cd2f352015-01-13 17:44:45 -080022import org.onlab.packet.VlanId;
Brian O'Connorabafb502014-12-02 22:26:20 -080023import org.onosproject.net.flow.FlowRule;
24import org.onosproject.net.flow.TrafficSelector;
25import org.onosproject.net.flow.criteria.Criteria;
26import org.onosproject.net.flow.criteria.Criteria.EthCriterion;
27import org.onosproject.net.flow.criteria.Criteria.EthTypeCriterion;
28import org.onosproject.net.flow.criteria.Criteria.IPCriterion;
29import org.onosproject.net.flow.criteria.Criteria.IPProtocolCriterion;
Jonathan Hart6cd2f352015-01-13 17:44:45 -080030import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
31import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.flow.criteria.Criteria.LambdaCriterion;
33import org.onosproject.net.flow.criteria.Criteria.PortCriterion;
34import org.onosproject.net.flow.criteria.Criteria.TcpPortCriterion;
35import org.onosproject.net.flow.criteria.Criteria.VlanIdCriterion;
36import org.onosproject.net.flow.criteria.Criteria.VlanPcpCriterion;
37import org.onosproject.net.flow.criteria.Criterion;
alshabibeec3a062014-09-17 18:01:26 -070038import org.projectfloodlight.openflow.protocol.OFFactory;
alshabib193525b2014-10-08 18:58:03 -070039import org.projectfloodlight.openflow.protocol.OFFlowAdd;
40import org.projectfloodlight.openflow.protocol.OFFlowDelete;
alshabibeec3a062014-09-17 18:01:26 -070041import org.projectfloodlight.openflow.protocol.OFFlowMod;
alshabibeec3a062014-09-17 18:01:26 -070042import org.projectfloodlight.openflow.protocol.match.Match;
43import org.projectfloodlight.openflow.protocol.match.MatchField;
Marc De Leenheer49087752014-10-23 13:54:09 -070044import org.projectfloodlight.openflow.types.CircuitSignalID;
alshabibeec3a062014-09-17 18:01:26 -070045import org.projectfloodlight.openflow.types.EthType;
46import org.projectfloodlight.openflow.types.IPv4Address;
Charles M.C. Chan52fae7d2015-01-17 00:35:53 +080047import org.projectfloodlight.openflow.types.IPv6Address;
alshabibeec3a062014-09-17 18:01:26 -070048import org.projectfloodlight.openflow.types.IpProtocol;
49import org.projectfloodlight.openflow.types.MacAddress;
50import org.projectfloodlight.openflow.types.Masked;
alshabibeec3a062014-09-17 18:01:26 -070051import org.projectfloodlight.openflow.types.OFPort;
52import org.projectfloodlight.openflow.types.OFVlanVidMatch;
Jonathan Hart34bc6142014-10-17 11:00:43 -070053import org.projectfloodlight.openflow.types.TransportPort;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -080054import org.projectfloodlight.openflow.types.U32;
Praseed Balakrishnan2dd5abd2014-11-03 14:56:28 -080055import org.projectfloodlight.openflow.types.U8;
alshabibeec3a062014-09-17 18:01:26 -070056import org.projectfloodlight.openflow.types.VlanPcp;
57import org.projectfloodlight.openflow.types.VlanVid;
58import org.slf4j.Logger;
59
Brian O'Connor427a1762014-11-19 18:40:32 -080060import java.util.Optional;
61
Jonathan Hart6cd2f352015-01-13 17:44:45 -080062import static org.slf4j.LoggerFactory.getLogger;
63
Jonathan Hart86e59352014-10-22 10:42:16 -070064/**
65 * Builder for OpenFlow flow mods based on FlowRules.
66 */
67public abstract class FlowModBuilder {
alshabibeec3a062014-09-17 18:01:26 -070068
69 private final Logger log = getLogger(getClass());
70
71 private final OFFactory factory;
Jonathan Hart86e59352014-10-22 10:42:16 -070072 private final FlowRule flowRule;
alshabibeec3a062014-09-17 18:01:26 -070073 private final TrafficSelector selector;
Brian O'Connor427a1762014-11-19 18:40:32 -080074 protected final Long xid;
alshabibeec3a062014-09-17 18:01:26 -070075
Jonathan Hart86e59352014-10-22 10:42:16 -070076 /**
77 * Creates a new flow mod builder.
78 *
79 * @param flowRule the flow rule to transform into a flow mod
80 * @param factory the OpenFlow factory to use to build the flow mod
Pavlin Radoslavov119fd5c2014-11-25 19:08:19 -080081 * @param xid the transaction ID
Jonathan Hart86e59352014-10-22 10:42:16 -070082 * @return the new flow mod builder
83 */
Brian O'Connor427a1762014-11-19 18:40:32 -080084 public static FlowModBuilder builder(FlowRule flowRule,
85 OFFactory factory, Optional<Long> xid) {
Jonathan Hart86e59352014-10-22 10:42:16 -070086 switch (factory.getVersion()) {
87 case OF_10:
Brian O'Connor427a1762014-11-19 18:40:32 -080088 return new FlowModBuilderVer10(flowRule, factory, xid);
Jonathan Hart86e59352014-10-22 10:42:16 -070089 case OF_13:
Brian O'Connor427a1762014-11-19 18:40:32 -080090 return new FlowModBuilderVer13(flowRule, factory, xid);
Jonathan Hart86e59352014-10-22 10:42:16 -070091 default:
92 throw new UnsupportedOperationException(
93 "No flow mod builder for protocol version " + factory.getVersion());
94 }
95 }
alshabibeec3a062014-09-17 18:01:26 -070096
Jonathan Hart86e59352014-10-22 10:42:16 -070097 /**
98 * Constructs a flow mod builder.
99 *
100 * @param flowRule the flow rule to transform into a flow mod
101 * @param factory the OpenFlow factory to use to build the flow mod
Pavlin Radoslavov119fd5c2014-11-25 19:08:19 -0800102 * @param xid the transaction ID
Jonathan Hart86e59352014-10-22 10:42:16 -0700103 */
Brian O'Connor427a1762014-11-19 18:40:32 -0800104 protected FlowModBuilder(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
alshabibeec3a062014-09-17 18:01:26 -0700105 this.factory = factory;
Jonathan Hart86e59352014-10-22 10:42:16 -0700106 this.flowRule = flowRule;
alshabibeec3a062014-09-17 18:01:26 -0700107 this.selector = flowRule.selector();
Brian O'Connor427a1762014-11-19 18:40:32 -0800108 this.xid = xid.orElse((long) 0);
109
alshabibeec3a062014-09-17 18:01:26 -0700110 }
111
Jonathan Hart86e59352014-10-22 10:42:16 -0700112 /**
113 * Builds an ADD flow mod.
114 *
115 * @return the flow mod
116 */
117 public abstract OFFlowAdd buildFlowAdd();
alshabibeec3a062014-09-17 18:01:26 -0700118
Jonathan Hart86e59352014-10-22 10:42:16 -0700119 /**
120 * Builds a MODIFY flow mod.
121 *
122 * @return the flow mod
123 */
124 public abstract OFFlowMod buildFlowMod();
alshabibeec3a062014-09-17 18:01:26 -0700125
Jonathan Hart86e59352014-10-22 10:42:16 -0700126 /**
127 * Builds a DELETE flow mod.
128 *
129 * @return the flow mod
130 */
131 public abstract OFFlowDelete buildFlowDel();
alshabibeec3a062014-09-17 18:01:26 -0700132
Jonathan Hart86e59352014-10-22 10:42:16 -0700133 /**
134 * Builds the match for the flow mod.
135 *
136 * @return the match
137 */
138 protected Match buildMatch() {
alshabibeec3a062014-09-17 18:01:26 -0700139 Match.Builder mBuilder = factory.buildMatch();
140 EthCriterion eth;
141 IPCriterion ip;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800142 Ip4Prefix ip4Prefix;
Charles M.C. Chan52fae7d2015-01-17 00:35:53 +0800143 Ip6Prefix ip6Prefix;
Jonathan Hart34bc6142014-10-17 11:00:43 -0700144 TcpPortCriterion tp;
alshabibeec3a062014-09-17 18:01:26 -0700145 for (Criterion c : selector.criteria()) {
146 switch (c.type()) {
147 case IN_PORT:
148 PortCriterion inport = (PortCriterion) c;
149 mBuilder.setExact(MatchField.IN_PORT, OFPort.of((int) inport.port().toLong()));
150 break;
151 case ETH_SRC:
152 eth = (EthCriterion) c;
153 mBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(eth.mac().toLong()));
154 break;
155 case ETH_DST:
156 eth = (EthCriterion) c;
157 mBuilder.setExact(MatchField.ETH_DST, MacAddress.of(eth.mac().toLong()));
158 break;
159 case ETH_TYPE:
160 EthTypeCriterion ethType = (EthTypeCriterion) c;
161 mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(ethType.ethType()));
162 break;
163 case IPV4_DST:
164 ip = (IPCriterion) c;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800165 ip4Prefix = ip.ip().getIp4Prefix();
166 if (ip4Prefix.prefixLength() != Ip4Prefix.MAX_MASK_LENGTH) {
167 Ip4Address maskAddr =
168 Ip4Address.makeMaskPrefix(ip4Prefix.prefixLength());
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700169 Masked<IPv4Address> maskedIp =
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800170 Masked.of(IPv4Address.of(ip4Prefix.address().toInt()),
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700171 IPv4Address.of(maskAddr.toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700172 mBuilder.setMasked(MatchField.IPV4_DST, maskedIp);
173 } else {
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700174 mBuilder.setExact(MatchField.IPV4_DST,
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800175 IPv4Address.of(ip4Prefix.address().toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700176 }
177 break;
178 case IPV4_SRC:
179 ip = (IPCriterion) c;
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800180 ip4Prefix = ip.ip().getIp4Prefix();
181 if (ip4Prefix.prefixLength() != Ip4Prefix.MAX_MASK_LENGTH) {
182 Ip4Address maskAddr =
183 Ip4Address.makeMaskPrefix(ip4Prefix.prefixLength());
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700184 Masked<IPv4Address> maskedIp =
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800185 Masked.of(IPv4Address.of(ip4Prefix.address().toInt()),
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700186 IPv4Address.of(maskAddr.toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700187 mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp);
188 } else {
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700189 mBuilder.setExact(MatchField.IPV4_SRC,
Pavlin Radoslavov23e398d2014-11-05 15:17:57 -0800190 IPv4Address.of(ip4Prefix.address().toInt()));
alshabibeec3a062014-09-17 18:01:26 -0700191 }
192 break;
193 case IP_PROTO:
194 IPProtocolCriterion p = (IPProtocolCriterion) c;
195 mBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(p.protocol()));
196 break;
197 case VLAN_PCP:
198 VlanPcpCriterion vpcp = (VlanPcpCriterion) c;
199 mBuilder.setExact(MatchField.VLAN_PCP, VlanPcp.of(vpcp.priority()));
200 break;
201 case VLAN_VID:
202 VlanIdCriterion vid = (VlanIdCriterion) c;
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800203
204 if (vid.vlanId().equals(VlanId.ANY)) {
205 mBuilder.setMasked(MatchField.VLAN_VID, OFVlanVidMatch.PRESENT,
206 OFVlanVidMatch.PRESENT);
207 } else {
208 mBuilder.setExact(MatchField.VLAN_VID,
209 OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
210 }
alshabibeec3a062014-09-17 18:01:26 -0700211 break;
Jonathan Hart34bc6142014-10-17 11:00:43 -0700212 case TCP_DST:
213 tp = (TcpPortCriterion) c;
214 mBuilder.setExact(MatchField.TCP_DST, TransportPort.of(tp.tcpPort()));
215 break;
216 case TCP_SRC:
217 tp = (TcpPortCriterion) c;
218 mBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(tp.tcpPort()));
219 break;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800220 case MPLS_LABEL:
221 Criteria.MplsCriterion mp = (Criteria.MplsCriterion) c;
222 mBuilder.setExact(MatchField.MPLS_LABEL,
223 U32.of(mp.label().intValue()));
224 break;
Marc De Leenheer49087752014-10-23 13:54:09 -0700225 case OCH_SIGID:
226 LambdaCriterion lc = (LambdaCriterion) c;
227 mBuilder.setExact(MatchField.OCH_SIGID,
228 new CircuitSignalID((byte) 1, (byte) 2, lc.lambda(), (short) 1));
229 break;
Praseed Balakrishnan2dd5abd2014-11-03 14:56:28 -0800230 case OCH_SIGTYPE:
231 Criteria.OpticalSignalTypeCriterion sc =
232 (Criteria.OpticalSignalTypeCriterion) c;
233 mBuilder.setExact(MatchField.OCH_SIGTYPE,
234 U8.of(sc.signalType()));
235 break;
Charles M.C. Chan52fae7d2015-01-17 00:35:53 +0800236 case IPV6_DST:
237 ip = (IPCriterion) c;
238 ip6Prefix = ip.ip().getIp6Prefix();
239 if (ip6Prefix.prefixLength() != Ip6Prefix.MAX_MASK_LENGTH) {
240 Ip6Address maskAddr =
241 Ip6Address.makeMaskPrefix(ip6Prefix.prefixLength());
242 Masked<IPv6Address> maskedIp =
243 Masked.of(IPv6Address.of(ip6Prefix.address().toString()),
244 IPv6Address.of(maskAddr.toString()));
245 mBuilder.setMasked(MatchField.IPV6_DST, maskedIp);
246 } else {
247 mBuilder.setExact(MatchField.IPV6_DST,
248 IPv6Address.of(ip6Prefix.address().toString()));
249 }
250 break;
251 case IPV6_SRC:
252 ip = (IPCriterion) c;
253 ip6Prefix = ip.ip().getIp6Prefix();
254 if (ip6Prefix.prefixLength() != Ip6Prefix.MAX_MASK_LENGTH) {
255 Ip6Address maskAddr =
256 Ip6Address.makeMaskPrefix(ip6Prefix.prefixLength());
257 Masked<IPv6Address> maskedIp =
258 Masked.of(IPv6Address.of(ip6Prefix.address().toString()),
259 IPv6Address.of(maskAddr.toString()));
260 mBuilder.setMasked(MatchField.IPV6_SRC, maskedIp);
261 } else {
262 mBuilder.setExact(MatchField.IPV6_SRC,
263 IPv6Address.of(ip6Prefix.address().toString()));
264 }
265 break;
Kunihiro Ishiguro0f9aba82015-01-15 17:14:17 -0800266 case ICMPV6_TYPE:
267 Icmpv6TypeCriterion icmpv6type = (Icmpv6TypeCriterion) c;
268 mBuilder.setExact(MatchField.ICMPV6_TYPE,
269 U8.of(icmpv6type.icmpv6Type().byteValue()));
270 break;
271 case ICMPV6_CODE:
272 Icmpv6CodeCriterion icmpv6code = (Icmpv6CodeCriterion) c;
273 mBuilder.setExact(MatchField.ICMPV6_CODE,
274 U8.of(icmpv6code.icmpv6Code().byteValue()));
275 break;
alshabibeec3a062014-09-17 18:01:26 -0700276 case ARP_OP:
277 case ARP_SHA:
278 case ARP_SPA:
279 case ARP_THA:
280 case ARP_TPA:
281 case ICMPV4_CODE:
282 case ICMPV4_TYPE:
alshabibeec3a062014-09-17 18:01:26 -0700283 case IN_PHY_PORT:
alshabibeec3a062014-09-17 18:01:26 -0700284 case IPV6_EXTHDR:
285 case IPV6_FLABEL:
286 case IPV6_ND_SLL:
287 case IPV6_ND_TARGET:
288 case IPV6_ND_TLL:
alshabibeec3a062014-09-17 18:01:26 -0700289 case IP_DSCP:
290 case IP_ECN:
291 case METADATA:
292 case MPLS_BOS:
alshabibeec3a062014-09-17 18:01:26 -0700293 case MPLS_TC:
294 case PBB_ISID:
295 case SCTP_DST:
296 case SCTP_SRC:
alshabibeec3a062014-09-17 18:01:26 -0700297 case TUNNEL_ID:
298 case UDP_DST:
299 case UDP_SRC:
300 default:
301 log.warn("Match type {} not yet implemented.", c.type());
302 }
303 }
304 return mBuilder.build();
305 }
306
Jonathan Hart86e59352014-10-22 10:42:16 -0700307 /**
308 * Returns the flow rule for this builder.
309 *
310 * @return the flow rule
311 */
312 protected FlowRule flowRule() {
313 return flowRule;
314 }
alshabib219ebaa2014-09-22 15:41:24 -0700315
Jonathan Hart86e59352014-10-22 10:42:16 -0700316 /**
317 * Returns the factory used for building OpenFlow constructs.
318 *
319 * @return the factory
320 */
321 protected OFFactory factory() {
322 return factory;
323 }
alshabib219ebaa2014-09-22 15:41:24 -0700324
alshabibeec3a062014-09-17 18:01:26 -0700325}