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