blob: f3655f7e676357ffc6689ab7bebc104f73e472c8 [file] [log] [blame]
alshabib6b5cfec2014-09-18 17:42:18 -07001package org.onlab.onos.provider.of.flow.impl;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
5import java.util.List;
6
7import org.onlab.onos.net.DeviceId;
8import org.onlab.onos.net.PortNumber;
9import org.onlab.onos.net.flow.DefaultFlowRule;
10import org.onlab.onos.net.flow.DefaultTrafficSelector;
11import org.onlab.onos.net.flow.DefaultTrafficTreatment;
12import org.onlab.onos.net.flow.FlowRule;
alshabiba7f7ca82014-09-22 11:41:23 -070013import org.onlab.onos.net.flow.FlowRule.FlowRuleState;
alshabib6b5cfec2014-09-18 17:42:18 -070014import org.onlab.onos.net.flow.TrafficSelector;
15import org.onlab.onos.net.flow.TrafficTreatment;
alshabib6b5cfec2014-09-18 17:42:18 -070016import org.onlab.onos.openflow.controller.Dpid;
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -070017import org.onlab.packet.IpPrefix;
alshabib6b5cfec2014-09-18 17:42:18 -070018import org.onlab.packet.MacAddress;
19import org.onlab.packet.VlanId;
20import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
alshabib6eb438a2014-10-01 16:39:37 -070021import org.projectfloodlight.openflow.protocol.OFFlowRemovedReason;
alshabib6b5cfec2014-09-18 17:42:18 -070022import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
alshabib19fdc122014-10-03 11:38:19 -070023import org.projectfloodlight.openflow.protocol.OFInstructionType;
alshabib6b5cfec2014-09-18 17:42:18 -070024import org.projectfloodlight.openflow.protocol.action.OFAction;
25import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
26import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
27import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
28import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
29import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
30import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
31import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
alshabib19fdc122014-10-03 11:38:19 -070032import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
33import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
alshabib6b5cfec2014-09-18 17:42:18 -070034import org.projectfloodlight.openflow.protocol.match.Match;
35import org.projectfloodlight.openflow.protocol.match.MatchField;
36import org.projectfloodlight.openflow.types.IPv4Address;
37import org.slf4j.Logger;
38
alshabib19fdc122014-10-03 11:38:19 -070039import com.google.common.collect.Lists;
40
alshabib6b5cfec2014-09-18 17:42:18 -070041public class FlowRuleBuilder {
42 private final Logger log = getLogger(getClass());
43
44 private final OFFlowStatsEntry stat;
45 private final OFFlowRemoved removed;
46
47 private final Match match;
48 private final List<OFAction> actions;
49
50 private final Dpid dpid;
51
alshabib19fdc122014-10-03 11:38:19 -070052 private final boolean addedRule;
alshabib6b5cfec2014-09-18 17:42:18 -070053
54
55 public FlowRuleBuilder(Dpid dpid, OFFlowStatsEntry entry) {
56 this.stat = entry;
57 this.match = entry.getMatch();
alshabib19fdc122014-10-03 11:38:19 -070058 this.actions = getActions(entry);
alshabib6b5cfec2014-09-18 17:42:18 -070059 this.dpid = dpid;
alshabib219ebaa2014-09-22 15:41:24 -070060 this.removed = null;
alshabib19fdc122014-10-03 11:38:19 -070061 this.addedRule = true;
alshabib6b5cfec2014-09-18 17:42:18 -070062 }
63
64 public FlowRuleBuilder(Dpid dpid, OFFlowRemoved removed) {
65 this.match = removed.getMatch();
66 this.removed = removed;
67
68 this.dpid = dpid;
69 this.actions = null;
70 this.stat = null;
alshabib19fdc122014-10-03 11:38:19 -070071 this.addedRule = false;
alshabib6b5cfec2014-09-18 17:42:18 -070072
73 }
74
75 public FlowRule build() {
alshabib19fdc122014-10-03 11:38:19 -070076 if (addedRule) {
alshabib6b5cfec2014-09-18 17:42:18 -070077 return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
78 buildSelector(), buildTreatment(), stat.getPriority(),
alshabiba7f7ca82014-09-22 11:41:23 -070079 FlowRuleState.ADDED, stat.getDurationNsec() / 1000000,
alshabib6b5cfec2014-09-18 17:42:18 -070080 stat.getPacketCount().getValue(), stat.getByteCount().getValue(),
alshabibba5ac482014-10-02 17:15:20 -070081 stat.getCookie().getValue(), false, stat.getIdleTimeout());
alshabib6b5cfec2014-09-18 17:42:18 -070082 } else {
83 // TODO: revisit potentially.
84 return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
85 buildSelector(), null, removed.getPriority(),
alshabiba7f7ca82014-09-22 11:41:23 -070086 FlowRuleState.REMOVED, removed.getDurationNsec() / 1000000,
alshabib6b5cfec2014-09-18 17:42:18 -070087 removed.getPacketCount().getValue(), removed.getByteCount().getValue(),
alshabib6eb438a2014-10-01 16:39:37 -070088 removed.getCookie().getValue(),
alshabibba5ac482014-10-02 17:15:20 -070089 removed.getReason() == OFFlowRemovedReason.IDLE_TIMEOUT.ordinal(),
90 stat.getIdleTimeout());
alshabib6b5cfec2014-09-18 17:42:18 -070091 }
92 }
93
alshabib19fdc122014-10-03 11:38:19 -070094 private List<OFAction> getActions(OFFlowStatsEntry entry) {
95 switch (entry.getVersion()) {
96 case OF_10:
97 return entry.getActions();
98 case OF_11:
99 case OF_12:
100 case OF_13:
101 List<OFInstruction> ins = entry.getInstructions();
102 for (OFInstruction in : ins) {
103 if (in.getType().equals(OFInstructionType.APPLY_ACTIONS)) {
104 OFInstructionApplyActions apply = (OFInstructionApplyActions) in;
105 return apply.getActions();
106 }
107 }
108 return Lists.newLinkedList();
109 default:
110 log.warn("Unknown OF version {}", entry.getVersion());
111 }
112 return Lists.newLinkedList();
113 }
alshabib6b5cfec2014-09-18 17:42:18 -0700114
115 private TrafficTreatment buildTreatment() {
116 TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder();
117 // If this is a drop rule
118 if (actions.size() == 0) {
alshabib010c31d2014-09-26 10:01:12 -0700119 builder.drop();
alshabib6b5cfec2014-09-18 17:42:18 -0700120 return builder.build();
121 }
122 for (OFAction act : actions) {
123 switch (act.getType()) {
124 case OUTPUT:
125 OFActionOutput out = (OFActionOutput) act;
alshabib010c31d2014-09-26 10:01:12 -0700126 builder.setOutput(
127 PortNumber.portNumber(out.getPort().getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700128 break;
129 case SET_VLAN_VID:
alshabib010c31d2014-09-26 10:01:12 -0700130 OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
131 builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
132 break;
133 case SET_VLAN_PCP:
alshabib6b5cfec2014-09-18 17:42:18 -0700134 OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
alshabib010c31d2014-09-26 10:01:12 -0700135 builder.setVlanId(VlanId.vlanId(pcp.getVlanPcp().getValue()));
alshabib6b5cfec2014-09-18 17:42:18 -0700136 break;
137 case SET_DL_DST:
138 OFActionSetDlDst dldst = (OFActionSetDlDst) act;
alshabib010c31d2014-09-26 10:01:12 -0700139 builder.setEthDst(
140 MacAddress.valueOf(dldst.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700141 break;
142 case SET_DL_SRC:
143 OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
alshabib010c31d2014-09-26 10:01:12 -0700144 builder.setEthSrc(
145 MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
alshabib6b5cfec2014-09-18 17:42:18 -0700146
147 break;
148 case SET_NW_DST:
149 OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
150 IPv4Address di = nwdst.getNwAddr();
151 if (di.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700152 builder.setIpDst(IpPrefix.valueOf(di.getInt(),
153 di.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700154 } else {
alshabib010c31d2014-09-26 10:01:12 -0700155 builder.setIpDst(IpPrefix.valueOf(di.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700156 }
157 break;
158 case SET_NW_SRC:
159 OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
160 IPv4Address si = nwsrc.getNwAddr();
161 if (si.isCidrMask()) {
alshabib010c31d2014-09-26 10:01:12 -0700162 builder.setIpSrc(IpPrefix.valueOf(si.getInt(),
163 si.asCidrMaskLength()));
alshabib6b5cfec2014-09-18 17:42:18 -0700164 } else {
alshabib010c31d2014-09-26 10:01:12 -0700165 builder.setIpSrc(IpPrefix.valueOf(si.getInt()));
alshabib6b5cfec2014-09-18 17:42:18 -0700166 }
167 break;
168 case SET_TP_DST:
169 case SET_TP_SRC:
170 case POP_MPLS:
171 case POP_PBB:
172 case POP_VLAN:
173 case PUSH_MPLS:
174 case PUSH_PBB:
175 case PUSH_VLAN:
176 case SET_FIELD:
177 case SET_MPLS_LABEL:
178 case SET_MPLS_TC:
179 case SET_MPLS_TTL:
180 case SET_NW_ECN:
181 case SET_NW_TOS:
182 case SET_NW_TTL:
183 case SET_QUEUE:
184 case STRIP_VLAN:
185 case COPY_TTL_IN:
186 case COPY_TTL_OUT:
187 case DEC_MPLS_TTL:
188 case DEC_NW_TTL:
189 case ENQUEUE:
190 case EXPERIMENTER:
191 case GROUP:
192 default:
193 log.warn("Action type {} not yet implemented.", act.getType());
194 }
195 }
196
197 return builder.build();
198 }
199
200 private TrafficSelector buildSelector() {
201 TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
202 for (MatchField<?> field : match.getMatchFields()) {
203 switch (field.id) {
204 case IN_PORT:
alshabib010c31d2014-09-26 10:01:12 -0700205 builder.matchInport(PortNumber
206 .portNumber(match.get(MatchField.IN_PORT).getPortNumber()));
alshabib6b5cfec2014-09-18 17:42:18 -0700207 break;
208 case ETH_SRC:
209 MacAddress sMac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700210 builder.matchEthSrc(sMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700211 break;
212 case ETH_DST:
213 MacAddress dMac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
alshabib010c31d2014-09-26 10:01:12 -0700214 builder.matchEthDst(dMac);
alshabib6b5cfec2014-09-18 17:42:18 -0700215 break;
216 case ETH_TYPE:
217 int ethType = match.get(MatchField.ETH_TYPE).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700218 builder.matchEthType((short) ethType);
alshabib6b5cfec2014-09-18 17:42:18 -0700219 break;
220 case IPV4_DST:
221 IPv4Address di = match.get(MatchField.IPV4_DST);
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700222 IpPrefix dip;
alshabib6b5cfec2014-09-18 17:42:18 -0700223 if (di.isCidrMask()) {
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700224 dip = IpPrefix.valueOf(di.getInt(), di.asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700225 } else {
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700226 dip = IpPrefix.valueOf(di.getInt());
alshabib6b5cfec2014-09-18 17:42:18 -0700227 }
alshabib010c31d2014-09-26 10:01:12 -0700228 builder.matchIPDst(dip);
alshabib6b5cfec2014-09-18 17:42:18 -0700229 break;
230 case IPV4_SRC:
231 IPv4Address si = match.get(MatchField.IPV4_SRC);
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700232 IpPrefix sip;
alshabib6b5cfec2014-09-18 17:42:18 -0700233 if (si.isCidrMask()) {
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700234 sip = IpPrefix.valueOf(si.getInt(), si.asCidrMaskLength());
alshabib6b5cfec2014-09-18 17:42:18 -0700235 } else {
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700236 sip = IpPrefix.valueOf(si.getInt());
alshabib6b5cfec2014-09-18 17:42:18 -0700237 }
alshabib010c31d2014-09-26 10:01:12 -0700238 builder.matchIPSrc(sip);
alshabib6b5cfec2014-09-18 17:42:18 -0700239 break;
240 case IP_PROTO:
241 short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
alshabib010c31d2014-09-26 10:01:12 -0700242 builder.matchIPProtocol((byte) proto);
alshabib6b5cfec2014-09-18 17:42:18 -0700243 break;
244 case VLAN_PCP:
245 byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
alshabib010c31d2014-09-26 10:01:12 -0700246 builder.matchVlanPcp(vlanPcp);
alshabib6b5cfec2014-09-18 17:42:18 -0700247 break;
248 case VLAN_VID:
249 VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
alshabib010c31d2014-09-26 10:01:12 -0700250 builder.matchVlanId(vlanId);
alshabib6b5cfec2014-09-18 17:42:18 -0700251 break;
252 case ARP_OP:
253 case ARP_SHA:
254 case ARP_SPA:
255 case ARP_THA:
256 case ARP_TPA:
257 case ICMPV4_CODE:
258 case ICMPV4_TYPE:
259 case ICMPV6_CODE:
260 case ICMPV6_TYPE:
261 case IN_PHY_PORT:
262 case IPV6_DST:
263 case IPV6_FLABEL:
264 case IPV6_ND_SLL:
265 case IPV6_ND_TARGET:
266 case IPV6_ND_TLL:
267 case IPV6_SRC:
268 case IP_DSCP:
269 case IP_ECN:
270 case METADATA:
271 case MPLS_LABEL:
272 case MPLS_TC:
273 case SCTP_DST:
274 case SCTP_SRC:
275 case TCP_DST:
276 case TCP_SRC:
277 case TUNNEL_ID:
278 case UDP_DST:
279 case UDP_SRC:
280 default:
281 log.warn("Match type {} not yet implemented.", field.id);
282
283
284 }
285 }
286 return builder.build();
287 }
288
289}