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