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