cf91860578ee47213114492ba82d44951d7febf5
[onosfw.git] /
1 /*
2  * Copyright 2014-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.flow.impl;
17
18 import static org.onosproject.net.flow.criteria.Criteria.matchLambda;
19 import static org.onosproject.net.flow.criteria.Criteria.matchOchSignalType;
20 import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupChannelSpacing;
21 import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupGridType;
22 import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupOchSignalType;
23 import static org.slf4j.LoggerFactory.getLogger;
24
25 import java.util.List;
26
27 import org.onlab.packet.Ip4Address;
28 import org.onlab.packet.Ip4Prefix;
29 import org.onlab.packet.Ip6Address;
30 import org.onlab.packet.Ip6Prefix;
31 import org.onlab.packet.MacAddress;
32 import org.onlab.packet.MplsLabel;
33 import org.onlab.packet.TpPort;
34 import org.onlab.packet.VlanId;
35 import org.onosproject.core.DefaultGroupId;
36 import org.onosproject.net.DeviceId;
37 import org.onosproject.net.Lambda;
38 import org.onosproject.net.PortNumber;
39 import org.onosproject.net.flow.DefaultFlowEntry;
40 import org.onosproject.net.flow.DefaultFlowRule;
41 import org.onosproject.net.flow.DefaultTrafficSelector;
42 import org.onosproject.net.flow.DefaultTrafficTreatment;
43 import org.onosproject.net.flow.FlowEntry;
44 import org.onosproject.net.flow.FlowEntry.FlowEntryState;
45 import org.onosproject.net.flow.FlowRule;
46 import org.onosproject.net.flow.TrafficSelector;
47 import org.onosproject.net.flow.TrafficTreatment;
48 import org.onosproject.net.flow.instructions.Instructions;
49 import org.onosproject.openflow.controller.Dpid;
50 import org.projectfloodlight.openflow.protocol.OFFlowMod;
51 import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
52 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
53 import org.projectfloodlight.openflow.protocol.action.OFAction;
54 import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
55 import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
56 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
57 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
58 import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls;
59 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
60 import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
61 import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
62 import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
63 import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
64 import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
65 import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
66 import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
67 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
68 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
69 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions;
70 import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteMetadata;
71 import org.projectfloodlight.openflow.protocol.match.Match;
72 import org.projectfloodlight.openflow.protocol.match.MatchField;
73 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
74 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
75 import org.projectfloodlight.openflow.protocol.ver13.OFFactoryVer13;
76 import org.projectfloodlight.openflow.types.CircuitSignalID;
77 import org.projectfloodlight.openflow.types.EthType;
78 import org.projectfloodlight.openflow.types.IPv4Address;
79 import org.projectfloodlight.openflow.types.IPv6Address;
80 import org.projectfloodlight.openflow.types.Masked;
81 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
82 import org.projectfloodlight.openflow.types.TransportPort;
83 import org.projectfloodlight.openflow.types.U32;
84 import org.projectfloodlight.openflow.types.U64;
85 import org.projectfloodlight.openflow.types.U8;
86 import org.projectfloodlight.openflow.types.VlanPcp;
87 import org.slf4j.Logger;
88
89 import com.google.common.collect.Lists;
90
91 public class FlowEntryBuilder {
92     private final Logger log = getLogger(getClass());
93
94     private final OFFlowStatsEntry stat;
95     private final OFFlowRemoved removed;
96     private final OFFlowMod flowMod;
97
98     private final Match match;
99
100     // All actions are contained in an OFInstruction. For OF1.0
101     // the instruction type is apply instruction (immediate set in ONOS speak)
102     private final List<OFInstruction> instructions;
103
104     private final Dpid dpid;
105
106     public enum FlowType { STAT, REMOVED, MOD }
107
108     private final FlowType type;
109
110     public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
111         this.stat = entry;
112         this.match = entry.getMatch();
113         this.instructions = getInstructions(entry);
114         this.dpid = dpid;
115         this.removed = null;
116         this.flowMod = null;
117         this.type = FlowType.STAT;
118     }
119
120     public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
121         this.match = removed.getMatch();
122         this.removed = removed;
123
124         this.dpid = dpid;
125         this.instructions = null;
126         this.stat = null;
127         this.flowMod = null;
128         this.type = FlowType.REMOVED;
129
130     }
131
132     public FlowEntryBuilder(Dpid dpid, OFFlowMod fm) {
133         this.match = fm.getMatch();
134         this.dpid = dpid;
135         this.instructions = getInstructions(fm);
136         this.type = FlowType.MOD;
137         this.flowMod = fm;
138         this.stat = null;
139         this.removed = null;
140     }
141
142     public FlowEntry build(FlowEntryState... state) {
143         FlowRule rule;
144         switch (this.type) {
145             case STAT:
146                 rule = DefaultFlowRule.builder()
147                         .forDevice(DeviceId.deviceId(Dpid.uri(dpid)))
148                         .withSelector(buildSelector())
149                         .withTreatment(buildTreatment())
150                         .withPriority(stat.getPriority())
151                         .makeTemporary(stat.getIdleTimeout())
152                         .withCookie(stat.getCookie().getValue())
153                         .forTable(stat.getTableId().getValue())
154                         .build();
155
156                 return new DefaultFlowEntry(rule, FlowEntryState.ADDED,
157                                       stat.getDurationSec(), stat.getPacketCount().getValue(),
158                                       stat.getByteCount().getValue());
159             case REMOVED:
160                 rule = DefaultFlowRule.builder()
161                         .forDevice(DeviceId.deviceId(Dpid.uri(dpid)))
162                         .withSelector(buildSelector())
163                         .withPriority(removed.getPriority())
164                         .makeTemporary(removed.getIdleTimeout())
165                         .withCookie(removed.getCookie().getValue())
166                         .forTable(removed.getTableId().getValue())
167                         .build();
168
169                 return new DefaultFlowEntry(rule, FlowEntryState.REMOVED, removed.getDurationSec(),
170                                       removed.getPacketCount().getValue(), removed.getByteCount().getValue());
171             case MOD:
172                 FlowEntryState flowState = state.length > 0 ? state[0] : FlowEntryState.FAILED;
173                 rule = DefaultFlowRule.builder()
174                         .forDevice(DeviceId.deviceId(Dpid.uri(dpid)))
175                         .withSelector(buildSelector())
176                         .withTreatment(buildTreatment())
177                         .withPriority(flowMod.getPriority())
178                         .makeTemporary(flowMod.getIdleTimeout())
179                         .withCookie(flowMod.getCookie().getValue())
180                         .forTable(flowMod.getTableId().getValue())
181                         .build();
182
183                 return new DefaultFlowEntry(rule, flowState, 0, 0, 0);
184             default:
185                 log.error("Unknown flow type : {}", this.type);
186                 return null;
187         }
188
189     }
190
191     private List<OFInstruction> getInstructions(OFFlowMod entry) {
192         switch (entry.getVersion()) {
193             case OF_10:
194                 return Lists.newArrayList(OFFactoryVer13.INSTANCE.instructions()
195                                                   .applyActions(
196                                                           entry.getActions()));
197             case OF_11:
198             case OF_12:
199             case OF_13:
200                 return entry.getInstructions();
201             default:
202                 log.warn("Unknown OF version {}", entry.getVersion());
203         }
204         return Lists.newLinkedList();
205     }
206
207     private List<OFInstruction> getInstructions(OFFlowStatsEntry entry) {
208         switch (entry.getVersion()) {
209             case OF_10:
210                 return Lists.newArrayList(
211                         OFFactoryVer13.INSTANCE.instructions().applyActions(entry.getActions()));
212             case OF_11:
213             case OF_12:
214             case OF_13:
215                 return entry.getInstructions();
216             default:
217                 log.warn("Unknown OF version {}", entry.getVersion());
218         }
219         return Lists.newLinkedList();
220     }
221
222     private TrafficTreatment buildTreatment() {
223         TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
224         for (OFInstruction in : instructions) {
225             switch (in.getType()) {
226                 case GOTO_TABLE:
227                     builder.transition(((int) ((OFInstructionGotoTable) in)
228                             .getTableId().getValue()));
229                     break;
230                 case WRITE_METADATA:
231                     OFInstructionWriteMetadata m = (OFInstructionWriteMetadata) in;
232                     builder.writeMetadata(m.getMetadata().getValue(),
233                                           m.getMetadataMask().getValue());
234                     break;
235                 case WRITE_ACTIONS:
236                     builder.deferred();
237                     buildActions(((OFInstructionWriteActions) in).getActions(),
238                                  builder);
239                     break;
240                 case APPLY_ACTIONS:
241                     builder.immediate();
242                     buildActions(((OFInstructionApplyActions) in).getActions(),
243                                  builder);
244                     break;
245                 case CLEAR_ACTIONS:
246                     builder.wipeDeferred();
247                     break;
248                 case EXPERIMENTER:
249                     break;
250                 case METER:
251                     break;
252                 default:
253                     log.warn("Unknown instructions type {}", in.getType());
254             }
255         }
256
257         return builder.build();
258     }
259
260     private TrafficTreatment.Builder buildActions(List<OFAction> actions,
261                                                   TrafficTreatment.Builder builder) {
262         for (OFAction act : actions) {
263             switch (act.getType()) {
264                 case OUTPUT:
265                     OFActionOutput out = (OFActionOutput) act;
266                     builder.setOutput(
267                             PortNumber.portNumber(out.getPort().getPortNumber()));
268                     break;
269                 case SET_VLAN_VID:
270                     OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
271                     builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
272                     break;
273                 case SET_VLAN_PCP:
274                     OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
275                     builder.setVlanPcp(pcp.getVlanPcp().getValue());
276                     break;
277                 case SET_DL_DST:
278                     OFActionSetDlDst dldst = (OFActionSetDlDst) act;
279                     builder.setEthDst(
280                             MacAddress.valueOf(dldst.getDlAddr().getLong()));
281                     break;
282                 case SET_DL_SRC:
283                     OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
284                     builder.setEthSrc(
285                             MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
286
287                     break;
288                 case SET_NW_DST:
289                     OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
290                     IPv4Address di = nwdst.getNwAddr();
291                     builder.setIpDst(Ip4Address.valueOf(di.getInt()));
292                     break;
293                 case SET_NW_SRC:
294                     OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
295                     IPv4Address si = nwsrc.getNwAddr();
296                     builder.setIpSrc(Ip4Address.valueOf(si.getInt()));
297                     break;
298                 case EXPERIMENTER:
299                     OFActionExperimenter exp = (OFActionExperimenter) act;
300                     if (exp.getExperimenter() == 0x80005A06 ||
301                             exp.getExperimenter() == 0x748771) {
302                         OFActionCircuit ct = (OFActionCircuit) exp;
303                         short lambda = ((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber();
304                         builder.add(Instructions.modL0Lambda(Lambda.indexedLambda(lambda)));
305                     } else {
306                         log.warn("Unsupported OFActionExperimenter {}", exp.getExperimenter());
307                     }
308                     break;
309                 case SET_FIELD:
310                     OFActionSetField setField = (OFActionSetField) act;
311                     handleSetField(builder, setField.getField());
312                     break;
313                 case POP_MPLS:
314                     OFActionPopMpls popMpls = (OFActionPopMpls) act;
315                     builder.popMpls((short) popMpls.getEthertype().getValue());
316                     break;
317                 case PUSH_MPLS:
318                     builder.pushMpls();
319                     break;
320                 case COPY_TTL_IN:
321                     builder.copyTtlIn();
322                     break;
323                 case COPY_TTL_OUT:
324                     builder.copyTtlOut();
325                     break;
326                 case DEC_MPLS_TTL:
327                     builder.decMplsTtl();
328                     break;
329                 case DEC_NW_TTL:
330                     builder.decNwTtl();
331                     break;
332                 case GROUP:
333                     OFActionGroup group = (OFActionGroup) act;
334                     builder.group(new DefaultGroupId(group.getGroup().getGroupNumber()));
335                     break;
336                 case STRIP_VLAN:
337                 case POP_VLAN:
338                     builder.popVlan();
339                     break;
340                 case PUSH_VLAN:
341                     builder.pushVlan();
342                     break;
343                 case SET_TP_DST:
344                 case SET_TP_SRC:
345                 case POP_PBB:
346                 case PUSH_PBB:
347                 case SET_MPLS_LABEL:
348                 case SET_MPLS_TC:
349                 case SET_MPLS_TTL:
350                 case SET_NW_ECN:
351                 case SET_NW_TOS:
352                 case SET_NW_TTL:
353                 case SET_QUEUE:
354
355                 case ENQUEUE:
356                 default:
357                     log.warn("Action type {} not yet implemented.", act.getType());
358             }
359         }
360         return builder;
361     }
362
363
364     private void handleSetField(TrafficTreatment.Builder builder, OFOxm<?> oxm) {
365         switch (oxm.getMatchField().id) {
366         case VLAN_PCP:
367             @SuppressWarnings("unchecked")
368             OFOxm<VlanPcp> vlanpcp = (OFOxm<VlanPcp>) oxm;
369             builder.setVlanPcp(vlanpcp.getValue().getValue());
370             break;
371         case VLAN_VID:
372             @SuppressWarnings("unchecked")
373             OFOxm<OFVlanVidMatch> vlanvid = (OFOxm<OFVlanVidMatch>) oxm;
374             builder.setVlanId(VlanId.vlanId(vlanvid.getValue().getVlan()));
375             break;
376         case ETH_DST:
377             @SuppressWarnings("unchecked")
378             OFOxm<org.projectfloodlight.openflow.types.MacAddress> ethdst =
379                     (OFOxm<org.projectfloodlight.openflow.types.MacAddress>) oxm;
380             builder.setEthDst(MacAddress.valueOf(ethdst.getValue().getLong()));
381             break;
382         case ETH_SRC:
383             @SuppressWarnings("unchecked")
384             OFOxm<org.projectfloodlight.openflow.types.MacAddress> ethsrc =
385                     (OFOxm<org.projectfloodlight.openflow.types.MacAddress>) oxm;
386             builder.setEthSrc(MacAddress.valueOf(ethsrc.getValue().getLong()));
387             break;
388         case IPV4_DST:
389             @SuppressWarnings("unchecked")
390             OFOxm<IPv4Address> ip4dst = (OFOxm<IPv4Address>) oxm;
391             builder.setIpDst(Ip4Address.valueOf(ip4dst.getValue().getInt()));
392             break;
393         case IPV4_SRC:
394             @SuppressWarnings("unchecked")
395             OFOxm<IPv4Address> ip4src = (OFOxm<IPv4Address>) oxm;
396             builder.setIpSrc(Ip4Address.valueOf(ip4src.getValue().getInt()));
397             break;
398         case MPLS_LABEL:
399             @SuppressWarnings("unchecked")
400             OFOxm<U32> labelId = (OFOxm<U32>) oxm;
401             builder.setMpls(MplsLabel.mplsLabel((int) labelId.getValue().getValue()));
402             break;
403         case MPLS_BOS:
404             @SuppressWarnings("unchecked")
405             OFOxm<U8> mplsBos = (OFOxm<U8>) oxm;
406             builder.setMplsBos(mplsBos.getValue() == U8.ZERO ? false : true);
407             break;
408         case TUNNEL_ID:
409             @SuppressWarnings("unchecked")
410             OFOxm<U64> tunnelId = (OFOxm<U64>) oxm;
411             builder.setTunnelId(tunnelId.getValue().getValue());
412             break;
413         case TCP_DST:
414             @SuppressWarnings("unchecked")
415             OFOxm<TransportPort> tcpdst = (OFOxm<TransportPort>) oxm;
416             builder.setTcpDst(TpPort.tpPort(tcpdst.getValue().getPort()));
417             break;
418         case TCP_SRC:
419             @SuppressWarnings("unchecked")
420             OFOxm<TransportPort> tcpsrc = (OFOxm<TransportPort>) oxm;
421             builder.setTcpSrc(TpPort.tpPort(tcpsrc.getValue().getPort()));
422             break;
423         case UDP_DST:
424             @SuppressWarnings("unchecked")
425             OFOxm<TransportPort> udpdst = (OFOxm<TransportPort>) oxm;
426             builder.setUdpDst(TpPort.tpPort(udpdst.getValue().getPort()));
427             break;
428         case UDP_SRC:
429             @SuppressWarnings("unchecked")
430             OFOxm<TransportPort> udpsrc = (OFOxm<TransportPort>) oxm;
431             builder.setUdpSrc(TpPort.tpPort(udpsrc.getValue().getPort()));
432             break;
433         case ARP_OP:
434         case ARP_SHA:
435         case ARP_SPA:
436         case ARP_THA:
437         case ARP_TPA:
438         case BSN_EGR_PORT_GROUP_ID:
439         case BSN_GLOBAL_VRF_ALLOWED:
440         case BSN_IN_PORTS_128:
441         case BSN_L3_DST_CLASS_ID:
442         case BSN_L3_INTERFACE_CLASS_ID:
443         case BSN_L3_SRC_CLASS_ID:
444         case BSN_LAG_ID:
445         case BSN_TCP_FLAGS:
446         case BSN_UDF0:
447         case BSN_UDF1:
448         case BSN_UDF2:
449         case BSN_UDF3:
450         case BSN_UDF4:
451         case BSN_UDF5:
452         case BSN_UDF6:
453         case BSN_UDF7:
454         case BSN_VLAN_XLATE_PORT_GROUP_ID:
455         case BSN_VRF:
456         case ETH_TYPE:
457         case ICMPV4_CODE:
458         case ICMPV4_TYPE:
459         case ICMPV6_CODE:
460         case ICMPV6_TYPE:
461         case IN_PHY_PORT:
462         case IN_PORT:
463         case IPV6_DST:
464         case IPV6_FLABEL:
465         case IPV6_ND_SLL:
466         case IPV6_ND_TARGET:
467         case IPV6_ND_TLL:
468         case IPV6_SRC:
469         case IP_DSCP:
470         case IP_ECN:
471         case IP_PROTO:
472         case METADATA:
473         case MPLS_TC:
474         case OCH_SIGID:
475         case OCH_SIGID_BASIC:
476         case OCH_SIGTYPE:
477         case OCH_SIGTYPE_BASIC:
478         case SCTP_DST:
479         case SCTP_SRC:
480         default:
481             log.warn("Set field type {} not yet implemented.", oxm.getMatchField().id);
482             break;
483         }
484     }
485
486     // CHECKSTYLE IGNORE MethodLength FOR NEXT 1 LINES
487     private TrafficSelector buildSelector() {
488         MacAddress mac;
489         Ip4Prefix ip4Prefix;
490         Ip6Address ip6Address;
491         Ip6Prefix ip6Prefix;
492
493         TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
494         for (MatchField<?> field : match.getMatchFields()) {
495             switch (field.id) {
496             case IN_PORT:
497                 builder.matchInPort(PortNumber
498                         .portNumber(match.get(MatchField.IN_PORT).getPortNumber()));
499                 break;
500             case IN_PHY_PORT:
501                 builder.matchInPhyPort(PortNumber
502                         .portNumber(match.get(MatchField.IN_PHY_PORT).getPortNumber()));
503                 break;
504             case METADATA:
505                 long metadata =
506                     match.get(MatchField.METADATA).getValue().getValue();
507                 builder.matchMetadata(metadata);
508                 break;
509             case ETH_DST:
510                 mac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
511                 builder.matchEthDst(mac);
512                 break;
513             case ETH_SRC:
514                 mac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
515                 builder.matchEthSrc(mac);
516                 break;
517             case ETH_TYPE:
518                 int ethType = match.get(MatchField.ETH_TYPE).getValue();
519                 if (ethType == EthType.VLAN_FRAME.getValue()) {
520                     builder.matchVlanId(VlanId.ANY);
521                 } else {
522                     builder.matchEthType((short) ethType);
523                 }
524                 break;
525             case VLAN_VID:
526                 VlanId vlanId = null;
527                 if (match.isPartiallyMasked(MatchField.VLAN_VID)) {
528                     Masked<OFVlanVidMatch> masked = match.getMasked(MatchField.VLAN_VID);
529                     if (masked.getValue().equals(OFVlanVidMatch.PRESENT)
530                             && masked.getMask().equals(OFVlanVidMatch.PRESENT)) {
531                         vlanId = VlanId.ANY;
532                     }
533                 } else {
534                     if (!match.get(MatchField.VLAN_VID).isPresentBitSet()) {
535                         vlanId = VlanId.NONE;
536                     } else {
537                         vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
538                     }
539                 }
540                 if (vlanId != null) {
541                     builder.matchVlanId(vlanId);
542                 }
543                 break;
544             case VLAN_PCP:
545                 byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
546                 builder.matchVlanPcp(vlanPcp);
547                 break;
548             case IP_DSCP:
549                 byte ipDscp = match.get(MatchField.IP_DSCP).getDscpValue();
550                 builder.matchIPDscp(ipDscp);
551                 break;
552             case IP_ECN:
553                 byte ipEcn = match.get(MatchField.IP_ECN).getEcnValue();
554                 builder.matchIPEcn(ipEcn);
555                 break;
556             case IP_PROTO:
557                 short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
558                 builder.matchIPProtocol((byte) proto);
559                 break;
560             case IPV4_SRC:
561                 if (match.isPartiallyMasked(MatchField.IPV4_SRC)) {
562                     Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_SRC);
563                     ip4Prefix = Ip4Prefix.valueOf(
564                             maskedIp.getValue().getInt(),
565                             maskedIp.getMask().asCidrMaskLength());
566                 } else {
567                     ip4Prefix = Ip4Prefix.valueOf(
568                             match.get(MatchField.IPV4_SRC).getInt(),
569                             Ip4Prefix.MAX_MASK_LENGTH);
570                 }
571                 builder.matchIPSrc(ip4Prefix);
572                 break;
573             case IPV4_DST:
574                 if (match.isPartiallyMasked(MatchField.IPV4_DST)) {
575                     Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_DST);
576                     ip4Prefix = Ip4Prefix.valueOf(
577                             maskedIp.getValue().getInt(),
578                             maskedIp.getMask().asCidrMaskLength());
579                 } else {
580                     ip4Prefix = Ip4Prefix.valueOf(
581                             match.get(MatchField.IPV4_DST).getInt(),
582                             Ip4Prefix.MAX_MASK_LENGTH);
583                 }
584                 builder.matchIPDst(ip4Prefix);
585                 break;
586             case TCP_SRC:
587                 builder.matchTcpSrc(TpPort.tpPort(match.get(MatchField.TCP_SRC).getPort()));
588                 break;
589             case TCP_DST:
590                 builder.matchTcpDst(TpPort.tpPort(match.get(MatchField.TCP_DST).getPort()));
591                 break;
592             case UDP_SRC:
593                 builder.matchUdpSrc(TpPort.tpPort(match.get(MatchField.UDP_SRC).getPort()));
594                 break;
595             case UDP_DST:
596                 builder.matchUdpDst(TpPort.tpPort(match.get(MatchField.UDP_DST).getPort()));
597                 break;
598             case MPLS_LABEL:
599                 builder.matchMplsLabel(MplsLabel.mplsLabel((int) match.get(MatchField.MPLS_LABEL)
600                                             .getValue()));
601                 break;
602             case MPLS_BOS:
603                 builder.matchMplsBos(match.get(MatchField.MPLS_BOS).getValue());
604                 break;
605             case SCTP_SRC:
606                 builder.matchSctpSrc(TpPort.tpPort(match.get(MatchField.SCTP_SRC).getPort()));
607                 break;
608             case SCTP_DST:
609                 builder.matchSctpDst(TpPort.tpPort(match.get(MatchField.SCTP_DST).getPort()));
610                 break;
611             case ICMPV4_TYPE:
612                 byte icmpType = (byte) match.get(MatchField.ICMPV4_TYPE).getType();
613                 builder.matchIcmpType(icmpType);
614                 break;
615             case ICMPV4_CODE:
616                 byte icmpCode = (byte) match.get(MatchField.ICMPV4_CODE).getCode();
617                 builder.matchIcmpCode(icmpCode);
618                 break;
619             case IPV6_SRC:
620                 if (match.isPartiallyMasked(MatchField.IPV6_SRC)) {
621                     Masked<IPv6Address> maskedIp = match.getMasked(MatchField.IPV6_SRC);
622                     ip6Prefix = Ip6Prefix.valueOf(
623                             maskedIp.getValue().getBytes(),
624                             maskedIp.getMask().asCidrMaskLength());
625                 } else {
626                     ip6Prefix = Ip6Prefix.valueOf(
627                             match.get(MatchField.IPV6_SRC).getBytes(),
628                             Ip6Prefix.MAX_MASK_LENGTH);
629                 }
630                 builder.matchIPv6Src(ip6Prefix);
631                 break;
632             case IPV6_DST:
633                 if (match.isPartiallyMasked(MatchField.IPV6_DST)) {
634                     Masked<IPv6Address> maskedIp = match.getMasked(MatchField.IPV6_DST);
635                     ip6Prefix = Ip6Prefix.valueOf(
636                             maskedIp.getValue().getBytes(),
637                             maskedIp.getMask().asCidrMaskLength());
638                 } else {
639                     ip6Prefix = Ip6Prefix.valueOf(
640                             match.get(MatchField.IPV6_DST).getBytes(),
641                             Ip6Prefix.MAX_MASK_LENGTH);
642                 }
643                 builder.matchIPv6Dst(ip6Prefix);
644                 break;
645             case IPV6_FLABEL:
646                 int flowLabel =
647                     match.get(MatchField.IPV6_FLABEL).getIPv6FlowLabelValue();
648                 builder.matchIPv6FlowLabel(flowLabel);
649                 break;
650             case ICMPV6_TYPE:
651                 byte icmpv6type = (byte) match.get(MatchField.ICMPV6_TYPE).getValue();
652                 builder.matchIcmpv6Type(icmpv6type);
653                 break;
654             case ICMPV6_CODE:
655                 byte icmpv6code = (byte) match.get(MatchField.ICMPV6_CODE).getValue();
656                 builder.matchIcmpv6Code(icmpv6code);
657                 break;
658             case IPV6_ND_TARGET:
659                 ip6Address =
660                     Ip6Address.valueOf(match.get(MatchField.IPV6_ND_TARGET).getBytes());
661                 builder.matchIPv6NDTargetAddress(ip6Address);
662                 break;
663             case IPV6_ND_SLL:
664                 mac = MacAddress.valueOf(match.get(MatchField.IPV6_ND_SLL).getLong());
665                 builder.matchIPv6NDSourceLinkLayerAddress(mac);
666                 break;
667             case IPV6_ND_TLL:
668                 mac = MacAddress.valueOf(match.get(MatchField.IPV6_ND_TLL).getLong());
669                 builder.matchIPv6NDTargetLinkLayerAddress(mac);
670                 break;
671             case IPV6_EXTHDR:
672                 builder.matchIPv6ExthdrFlags((short) match.get(MatchField.IPV6_EXTHDR)
673                         .getValue());
674                 break;
675             case OCH_SIGID:
676                 CircuitSignalID sigId = match.get(MatchField.OCH_SIGID);
677                 builder.add(matchLambda(Lambda.ochSignal(
678                                 lookupGridType(sigId.getGridType()), lookupChannelSpacing(sigId.getChannelSpacing()),
679                                 sigId.getChannelNumber(), sigId.getSpectralWidth())
680                 ));
681                 break;
682             case OCH_SIGTYPE:
683                 U8 sigType = match.get(MatchField.OCH_SIGTYPE);
684                 builder.add(matchOchSignalType(lookupOchSignalType((byte) sigType.getValue())));
685                 break;
686             case TUNNEL_ID:
687                 long tunnelId = match.get(MatchField.TUNNEL_ID).getValue();
688                 builder.matchTunnelId(tunnelId);
689                 break;
690             case ARP_OP:
691             case ARP_SHA:
692             case ARP_SPA:
693             case ARP_THA:
694             case ARP_TPA:
695             case MPLS_TC:
696             default:
697                 log.warn("Match type {} not yet implemented.", field.id);
698             }
699         }
700         return builder.build();
701     }
702 }