blob: 8c009a7bd34afdd24864068d3d043113c226ef92 [file] [log] [blame]
alshabibeec3a062014-09-17 18:01:26 -07001package org.onlab.onos.provider.of.flow.impl;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
5import java.util.Collections;
6import java.util.LinkedList;
7import java.util.List;
8
alshabib6b5cfec2014-09-18 17:42:18 -07009import org.onlab.onos.net.flow.FlowId;
alshabibeec3a062014-09-17 18:01:26 -070010import org.onlab.onos.net.flow.FlowRule;
11import org.onlab.onos.net.flow.TrafficSelector;
12import org.onlab.onos.net.flow.TrafficTreatment;
13import org.onlab.onos.net.flow.criteria.Criteria.EthCriterion;
14import org.onlab.onos.net.flow.criteria.Criteria.EthTypeCriterion;
15import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion;
16import org.onlab.onos.net.flow.criteria.Criteria.IPProtocolCriterion;
17import org.onlab.onos.net.flow.criteria.Criteria.PortCriterion;
18import org.onlab.onos.net.flow.criteria.Criteria.VlanIdCriterion;
19import org.onlab.onos.net.flow.criteria.Criteria.VlanPcpCriterion;
20import org.onlab.onos.net.flow.criteria.Criterion;
21import org.onlab.onos.net.flow.instructions.Instruction;
22import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
23import org.onlab.onos.net.flow.instructions.L2ModificationInstruction;
24import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
25import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
26import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
27import org.onlab.onos.net.flow.instructions.L3ModificationInstruction;
28import org.onlab.onos.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
29import org.projectfloodlight.openflow.protocol.OFFactory;
30import org.projectfloodlight.openflow.protocol.OFFlowMod;
31import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
32import org.projectfloodlight.openflow.protocol.action.OFAction;
33import org.projectfloodlight.openflow.protocol.match.Match;
34import org.projectfloodlight.openflow.protocol.match.MatchField;
35import org.projectfloodlight.openflow.types.EthType;
36import org.projectfloodlight.openflow.types.IPv4Address;
37import org.projectfloodlight.openflow.types.IpProtocol;
38import org.projectfloodlight.openflow.types.MacAddress;
39import org.projectfloodlight.openflow.types.Masked;
40import org.projectfloodlight.openflow.types.OFBufferId;
41import org.projectfloodlight.openflow.types.OFPort;
42import org.projectfloodlight.openflow.types.OFVlanVidMatch;
alshabib6b5cfec2014-09-18 17:42:18 -070043import org.projectfloodlight.openflow.types.U64;
alshabibeec3a062014-09-17 18:01:26 -070044import org.projectfloodlight.openflow.types.VlanPcp;
45import org.projectfloodlight.openflow.types.VlanVid;
46import org.slf4j.Logger;
47
48
49public class FlowModBuilder {
50
51 private final Logger log = getLogger(getClass());
52
53 private final OFFactory factory;
54 private final TrafficTreatment treatment;
55 private final TrafficSelector selector;
56
57 private final int priority;
58
alshabib6b5cfec2014-09-18 17:42:18 -070059 private final FlowId cookie;
60
alshabibeec3a062014-09-17 18:01:26 -070061
62
63 public FlowModBuilder(FlowRule flowRule, OFFactory factory) {
64 this.factory = factory;
65 this.treatment = flowRule.treatment();
66 this.selector = flowRule.selector();
67 this.priority = flowRule.priority();
alshabib6b5cfec2014-09-18 17:42:18 -070068 this.cookie = flowRule.id();
alshabibeec3a062014-09-17 18:01:26 -070069 }
70
71 public OFFlowMod buildFlowMod() {
72 Match match = buildMatch();
73 List<OFAction> actions = buildActions();
74
75 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
76 OFFlowMod fm = factory.buildFlowModify()
alshabib6b5cfec2014-09-18 17:42:18 -070077 .setCookie(U64.of(cookie.value()))
alshabibeec3a062014-09-17 18:01:26 -070078 .setBufferId(OFBufferId.NO_BUFFER)
79 .setActions(actions)
80 .setMatch(match)
81 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
82 .setIdleTimeout(10)
83 .setHardTimeout(10)
84 .setPriority(priority)
85 .build();
86
87 return fm;
88
89 }
90
alshabib219ebaa2014-09-22 15:41:24 -070091 public OFFlowMod buildFlowDel() {
92 Match match = buildMatch();
93 List<OFAction> actions = buildActions();
94
95 OFFlowMod fm = factory.buildFlowDelete()
96 .setCookie(U64.of(cookie.value()))
97 .setBufferId(OFBufferId.NO_BUFFER)
98 .setActions(actions)
99 .setMatch(match)
100 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
101 .setIdleTimeout(10)
102 .setHardTimeout(10)
103 .setPriority(priority)
104 .build();
105
106 return fm;
107 }
108
alshabibeec3a062014-09-17 18:01:26 -0700109 private List<OFAction> buildActions() {
110 List<OFAction> acts = new LinkedList<>();
111 for (Instruction i : treatment.instructions()) {
112 switch (i.type()) {
113 case DROP:
114 log.warn("Saw drop action; assigning drop action");
115 return new LinkedList<>();
116 case L2MODIFICATION:
117 acts.add(buildL2Modification(i));
118 case L3MODIFICATION:
119 acts.add(buildL3Modification(i));
120 case OUTPUT:
121 OutputInstruction out = (OutputInstruction) i;
122 acts.add(factory.actions().buildOutput().setPort(
123 OFPort.of((int) out.port().toLong())).build());
124 break;
125 case GROUP:
126 default:
127 log.warn("Instruction type {} not yet implemented.", i.type());
128 }
129 }
130
131 return acts;
132 }
133
134 private OFAction buildL3Modification(Instruction i) {
135 L3ModificationInstruction l3m = (L3ModificationInstruction) i;
136 ModIPInstruction ip;
137 switch (l3m.subtype()) {
138 case L3_DST:
139 ip = (ModIPInstruction) i;
140 return factory.actions().setNwDst(IPv4Address.of(ip.ip().toInt()));
141 case L3_SRC:
142 ip = (ModIPInstruction) i;
143 return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toInt()));
144 default:
145 log.warn("Unimplemented action type {}.", l3m.subtype());
146 break;
147 }
148 return null;
149 }
150
151 private OFAction buildL2Modification(Instruction i) {
152 L2ModificationInstruction l2m = (L2ModificationInstruction) i;
153 ModEtherInstruction eth;
154 switch (l2m.subtype()) {
155 case L2_DST:
156 eth = (ModEtherInstruction) l2m;
157 return factory.actions().setDlDst(MacAddress.of(eth.mac().toLong()));
158 case L2_SRC:
159 eth = (ModEtherInstruction) l2m;
160 return factory.actions().setDlSrc(MacAddress.of(eth.mac().toLong()));
161 case VLAN_ID:
162 ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
163 return factory.actions().setVlanVid(VlanVid.ofVlan(vlanId.vlanId.toShort()));
164 case VLAN_PCP:
165 ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
166 return factory.actions().setVlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
167 default:
168 log.warn("Unimplemented action type {}.", l2m.subtype());
169 break;
170 }
171 return null;
172 }
173
174 private Match buildMatch() {
175 Match.Builder mBuilder = factory.buildMatch();
176 EthCriterion eth;
177 IPCriterion ip;
178 for (Criterion c : selector.criteria()) {
179 switch (c.type()) {
180 case IN_PORT:
181 PortCriterion inport = (PortCriterion) c;
182 mBuilder.setExact(MatchField.IN_PORT, OFPort.of((int) inport.port().toLong()));
183 break;
184 case ETH_SRC:
185 eth = (EthCriterion) c;
186 mBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(eth.mac().toLong()));
187 break;
188 case ETH_DST:
189 eth = (EthCriterion) c;
190 mBuilder.setExact(MatchField.ETH_DST, MacAddress.of(eth.mac().toLong()));
191 break;
192 case ETH_TYPE:
193 EthTypeCriterion ethType = (EthTypeCriterion) c;
194 mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(ethType.ethType()));
195 break;
196 case IPV4_DST:
197 ip = (IPCriterion) c;
198 if (ip.ip().isMasked()) {
199 Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()),
200 IPv4Address.of(ip.ip().netmask().toInt()));
201 mBuilder.setMasked(MatchField.IPV4_DST, maskedIp);
202 } else {
203 mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toInt()));
204 }
205 break;
206 case IPV4_SRC:
207 ip = (IPCriterion) c;
208 if (ip.ip().isMasked()) {
209 Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()),
210 IPv4Address.of(ip.ip().netmask().toInt()));
211 mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp);
212 } else {
213 mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toInt()));
214 }
215 break;
216 case IP_PROTO:
217 IPProtocolCriterion p = (IPProtocolCriterion) c;
218 mBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(p.protocol()));
219 break;
220 case VLAN_PCP:
221 VlanPcpCriterion vpcp = (VlanPcpCriterion) c;
222 mBuilder.setExact(MatchField.VLAN_PCP, VlanPcp.of(vpcp.priority()));
223 break;
224 case VLAN_VID:
225 VlanIdCriterion vid = (VlanIdCriterion) c;
226 mBuilder.setExact(MatchField.VLAN_VID,
227 OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
228 break;
229 case ARP_OP:
230 case ARP_SHA:
231 case ARP_SPA:
232 case ARP_THA:
233 case ARP_TPA:
234 case ICMPV4_CODE:
235 case ICMPV4_TYPE:
236 case ICMPV6_CODE:
237 case ICMPV6_TYPE:
238 case IN_PHY_PORT:
239 case IPV6_DST:
240 case IPV6_EXTHDR:
241 case IPV6_FLABEL:
242 case IPV6_ND_SLL:
243 case IPV6_ND_TARGET:
244 case IPV6_ND_TLL:
245 case IPV6_SRC:
246 case IP_DSCP:
247 case IP_ECN:
248 case METADATA:
249 case MPLS_BOS:
250 case MPLS_LABEL:
251 case MPLS_TC:
252 case PBB_ISID:
253 case SCTP_DST:
254 case SCTP_SRC:
255 case TCP_DST:
256 case TCP_SRC:
257 case TUNNEL_ID:
258 case UDP_DST:
259 case UDP_SRC:
260 default:
261 log.warn("Match type {} not yet implemented.", c.type());
262 }
263 }
264 return mBuilder.build();
265 }
266
alshabib219ebaa2014-09-22 15:41:24 -0700267
268
alshabibeec3a062014-09-17 18:01:26 -0700269}