BUG-1167: missing Notification of FLOW_REMOVED
[controller.git] / opendaylight / md-sal / compatibility / sal-compatibility / src / main / java / org / opendaylight / controller / sal / compatibility / ToSalConversionsUtils.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.sal.compatibility;
9
10 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
11 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
12 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
13 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
14 import static org.opendaylight.controller.sal.match.MatchType.DL_DST;
15 import static org.opendaylight.controller.sal.match.MatchType.DL_SRC;
16 import static org.opendaylight.controller.sal.match.MatchType.DL_TYPE;
17 import static org.opendaylight.controller.sal.match.MatchType.DL_VLAN;
18 import static org.opendaylight.controller.sal.match.MatchType.DL_VLAN_PR;
19 import static org.opendaylight.controller.sal.match.MatchType.NW_DST;
20 import static org.opendaylight.controller.sal.match.MatchType.NW_PROTO;
21 import static org.opendaylight.controller.sal.match.MatchType.NW_SRC;
22 import static org.opendaylight.controller.sal.match.MatchType.NW_TOS;
23 import static org.opendaylight.controller.sal.match.MatchType.TP_DST;
24 import static org.opendaylight.controller.sal.match.MatchType.TP_SRC;
25
26 import java.net.InetAddress;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.List;
30
31 import org.opendaylight.controller.sal.action.Controller;
32 import org.opendaylight.controller.sal.action.Drop;
33 import org.opendaylight.controller.sal.action.Flood;
34 import org.opendaylight.controller.sal.action.FloodAll;
35 import org.opendaylight.controller.sal.action.HwPath;
36 import org.opendaylight.controller.sal.action.Loopback;
37 import org.opendaylight.controller.sal.action.Output;
38 import org.opendaylight.controller.sal.action.PopVlan;
39 import org.opendaylight.controller.sal.action.PushVlan;
40 import org.opendaylight.controller.sal.action.SetDlDst;
41 import org.opendaylight.controller.sal.action.SetDlSrc;
42 import org.opendaylight.controller.sal.action.SetDlType;
43 import org.opendaylight.controller.sal.action.SetNextHop;
44 import org.opendaylight.controller.sal.action.SetNwDst;
45 import org.opendaylight.controller.sal.action.SetNwSrc;
46 import org.opendaylight.controller.sal.action.SetNwTos;
47 import org.opendaylight.controller.sal.action.SetTpDst;
48 import org.opendaylight.controller.sal.action.SetTpSrc;
49 import org.opendaylight.controller.sal.action.SetVlanCfi;
50 import org.opendaylight.controller.sal.action.SetVlanId;
51 import org.opendaylight.controller.sal.action.SetVlanPcp;
52 import org.opendaylight.controller.sal.action.SwPath;
53 import org.opendaylight.controller.sal.core.ConstructionException;
54 import org.opendaylight.controller.sal.core.Node;
55 import org.opendaylight.controller.sal.core.NodeConnector;
56 import org.opendaylight.controller.sal.flowprogrammer.Flow;
57 import org.opendaylight.controller.sal.match.Match;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCase;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCase;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCase;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCase;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCase;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCase;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCase;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetMplsTtlActionCase;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCase;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCase;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCase;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCase;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTtlActionCase;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueActionCase;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCase;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCase;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.GenericFlowAttributes;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddress;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddress;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanId;
119
120 import com.google.common.net.InetAddresses;
121
122 public class ToSalConversionsUtils {
123
124     private ToSalConversionsUtils() {
125
126     }
127
128     public static Flow toFlow(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source, Node node) {
129         final Flow target = new Flow();
130         genericFlowToAdFlow(source, target);
131         
132         target.setMatch(toMatch(source.getMatch()));
133
134         List<Action> actions = getAction(source);
135         if (actions != null) {
136             target.setActions(actionFrom(actions, node));
137         }
138
139         return target;
140     }
141     
142     /**
143      * @param source notification, missing instructions
144      * @param node corresponding node where the flow change occured
145      * @return ad-sal node, build from given data
146      */
147     public static Flow toFlow(SwitchFlowRemoved source, Node node) {
148         final Flow target = new Flow();
149         genericFlowToAdFlow(source, target);
150
151         target.setMatch(toMatch(source.getMatch()));
152
153         return target;
154     }
155
156     /**
157      * @param source
158      * @param target
159      */
160     private static void genericFlowToAdFlow(GenericFlowAttributes source,
161             final Flow target) {
162         Integer hardTimeout = source.getHardTimeout();
163         if (hardTimeout != null) {
164             target.setHardTimeout(hardTimeout.shortValue());
165         }
166
167         Integer idleTimeout = source.getIdleTimeout();
168         if (idleTimeout != null) {
169             target.setIdleTimeout(idleTimeout.shortValue());
170         }
171
172         Integer priority = source.getPriority();
173         if (priority != null) {
174             target.setPriority(priority.shortValue());
175         }
176         target.setId(source.getCookie().getValue().longValue());
177     }
178     
179     public static List<Action> getAction(
180             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source) {
181         if (source.getInstructions() != null) {
182             for (Instruction instruction : source.getInstructions().getInstruction()) {
183                 if (instruction.getInstruction() instanceof ApplyActionsCase) {
184                     return (((ApplyActionsCase) instruction.getInstruction()).getApplyActions().getAction());
185                 }
186             }
187         }
188         // TODO Auto-generated method stub
189         return Collections.emptyList();
190     }
191
192     public static List<org.opendaylight.controller.sal.action.Action> actionFrom(List<Action> actions, Node node) {
193         List<org.opendaylight.controller.sal.action.Action> targetAction = new ArrayList<>();
194         for (Action action : actions) {
195             org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action sourceAction = action
196                     .getAction();
197
198             if (sourceAction instanceof ControllerActionCase) {
199                 targetAction.add(new Controller());
200             } else if (sourceAction instanceof OutputActionCase) {
201
202                 Uri nodeConnector = ((OutputActionCase) sourceAction).getOutputAction().getOutputNodeConnector();
203                 if (nodeConnector != null) {
204                     //for (Uri uri : nodeConnectors) {
205                         targetAction.add(new Output(fromNodeConnectorRef(nodeConnector, node)));
206                     //}
207                 }
208             } else if (sourceAction instanceof PopMplsActionCase) {
209                 // TODO: define maping
210             } else if (sourceAction instanceof PushMplsActionCase) {
211                 // TODO: define maping
212             } else if (sourceAction instanceof PushPbbActionCase) {
213                 // TODO: define maping
214             } else if (sourceAction instanceof SetMplsTtlActionCase) {
215                 // TODO: define maping
216                 // targetAction = //no action to map
217             } else if (sourceAction instanceof SetNwTtlActionCase) {
218                 // TODO: define maping
219             } else if (sourceAction instanceof SetQueueActionCase) {
220                 // TODO: define maping
221                 // targetAction = //no action to map
222             } else if (sourceAction instanceof DropActionCase) {
223                 targetAction.add(new Drop());
224             } else if (sourceAction instanceof FloodActionCase) {
225                 targetAction.add(new Flood());
226             } else if (sourceAction instanceof FloodAllActionCase) {
227                 targetAction.add(new FloodAll());
228             } else if (sourceAction instanceof HwPathActionCase) {
229                 targetAction.add(new HwPath());
230             } else if (sourceAction instanceof LoopbackActionCase) {
231                 targetAction.add(new Loopback());
232             } else if (sourceAction instanceof PopVlanActionCase) {
233                 targetAction.add(new PopVlan());
234             } else if (sourceAction instanceof PushVlanActionCase) {
235                 PushVlanActionCase pushVlanAction = (PushVlanActionCase) sourceAction;
236                 PushVlan pushVlan = pushVlanFrom(pushVlanAction.getPushVlanAction());
237                 if (pushVlan != null) {
238                     targetAction.add(pushVlan);
239                 }
240             } else if (sourceAction instanceof SetDlDstActionCase) {
241                 MacAddress addressL2Dest = ((SetDlDstActionCase) sourceAction).getSetDlDstAction().getAddress();
242                 if (addressL2Dest != null) {
243                     targetAction.add(new SetDlDst(bytesFrom(addressL2Dest)));
244                 }
245             } else if (sourceAction instanceof SetDlSrcActionCase) {
246                 MacAddress addressL2Src = ((SetDlSrcActionCase) sourceAction).getSetDlSrcAction().getAddress();
247                 if (addressL2Src != null) {
248                     targetAction.add(new SetDlSrc(bytesFrom(addressL2Src)));
249
250                 }
251             } else if (sourceAction instanceof SetDlTypeActionCase) {
252                 EtherType dlType = ((SetDlTypeActionCase) sourceAction).getSetDlTypeAction().getDlType();
253                 if (dlType != null) {
254                     Long dlTypeValue = dlType.getValue();
255                     if (dlTypeValue != null) {
256                         targetAction.add(new SetDlType(dlTypeValue.intValue()));
257                     }
258                 }
259             } else if (sourceAction instanceof SetNextHopActionCase) {
260                 Address addressL3 = ((SetNextHopActionCase) sourceAction).getSetNextHopAction().getAddress();
261
262                 InetAddress inetAddress = inetAddressFrom(addressL3);
263                 if (inetAddress != null) {
264                     targetAction.add(new SetNextHop(inetAddress));
265                 }
266             } else if (sourceAction instanceof SetNwDstActionCase) {
267                 Address addressL3 = ((SetNwDstActionCase) sourceAction).getSetNwDstAction().getAddress();
268
269                 InetAddress inetAddress = inetAddressFrom(addressL3);
270                 if (inetAddress != null) {
271                     targetAction.add(new SetNwDst(inetAddress));
272                 }
273             } else if (sourceAction instanceof SetNwSrcActionCase) {
274                 Address addressL3 = ((SetNwSrcActionCase) sourceAction).getSetNwSrcAction().getAddress();
275
276                 InetAddress inetAddress = inetAddressFrom(addressL3);
277                 if (inetAddress != null) {
278                     targetAction.add(new SetNwSrc(inetAddress));
279                 }
280             } else if (sourceAction instanceof SetNwTosActionCase) {
281                 Integer tos = ((SetNwTosActionCase) sourceAction).getSetNwTosAction().getTos();
282                 if (tos != null) {
283                     targetAction.add(new SetNwTos(tos));
284                 }
285             } else if (sourceAction instanceof SetTpDstActionCase) {
286                 PortNumber port = ((SetTpDstActionCase) sourceAction).getSetTpDstAction().getPort();
287                 if (port != null) {
288                     Integer portValue = port.getValue();
289                     if (port.getValue() != null) {
290                         targetAction.add(new SetTpDst(portValue));
291                     }
292                 }
293             } else if (sourceAction instanceof SetTpSrcActionCase) {
294                 PortNumber port = ((SetTpSrcActionCase) sourceAction).getSetTpSrcAction().getPort();
295                 if (port != null) {
296                     Integer portValue = port.getValue();
297                     if (port.getValue() != null) {
298                         targetAction.add(new SetTpSrc(portValue));
299                     }
300                 }
301             } else if (sourceAction instanceof SetVlanCfiActionCase) {
302                 VlanCfi vlanCfi = ((SetVlanCfiActionCase) sourceAction).getSetVlanCfiAction().getVlanCfi();
303                 if (vlanCfi != null) {
304                     Integer vlanCfiValue = vlanCfi.getValue();
305                     if (vlanCfiValue != null) {
306                         targetAction.add(new SetVlanCfi(vlanCfiValue));
307                     }
308                 }
309             } else if (sourceAction instanceof SetVlanIdActionCase) {
310                 org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanID = ((SetVlanIdActionCase) sourceAction).getSetVlanIdAction()
311                         .getVlanId();
312                 if (vlanID != null) {
313                     Integer vlanIdValue = vlanID.getValue();
314                     if (vlanIdValue != null) {
315                         targetAction.add(new SetVlanId(vlanIdValue));
316                     }
317                 }
318             } else if (sourceAction instanceof SetVlanPcpActionCase) {
319                 VlanPcp vlanPcp = ((SetVlanPcpActionCase) sourceAction).getSetVlanPcpAction().getVlanPcp();
320                 if (vlanPcp != null) {
321                     Short vlanPcpValue = vlanPcp.getValue();
322                     if (vlanPcpValue != null) {
323                         targetAction.add(new SetVlanPcp(vlanPcpValue));
324                     }
325                 }
326             } else if (sourceAction instanceof SwPathActionCase) {
327                 targetAction.add(new SwPath());
328             }
329         }
330
331         return targetAction;
332     }
333
334     private static InetAddress inetAddressFrom(Address addressL3) {
335         if (addressL3 != null) {
336             if (addressL3 instanceof Ipv4) {
337                 Ipv4Prefix addressL3Ipv4 = ((Ipv4) addressL3).getIpv4Address();
338                 if (addressL3Ipv4 != null) {
339                     return inetAddressFrom(addressL3Ipv4);
340                 }
341             } else if (addressL3 instanceof Ipv6) {
342                 Ipv6Prefix addressL3Ipv6 = ((Ipv6) addressL3).getIpv6Address();
343                 if (addressL3Ipv6 != null) {
344                     return inetAddressFrom(addressL3Ipv6);
345                 }
346             }
347         }
348         return null;
349     }
350
351     private static PushVlan pushVlanFrom(org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanAction pushVlanAction) {
352         final int tag;
353         final int pcp;
354         final int cfi;
355         final int vlanId;
356
357         if (pushVlanAction.getTag() != null) {
358             tag = pushVlanAction.getTag();
359             if (pushVlanAction.getPcp() != null) {
360                 pcp = pushVlanAction.getPcp();
361                 if (pushVlanAction.getCfi() != null && pushVlanAction.getCfi().getValue() != null) {
362                     cfi = pushVlanAction.getCfi().getValue();
363                     if (pushVlanAction.getVlanId() != null && pushVlanAction.getVlanId().getValue() != null) {
364                         vlanId = pushVlanAction.getVlanId().getValue();
365                         return new PushVlan(tag, pcp, cfi, vlanId);
366                     }
367                 }
368             }
369         }
370         return null;
371     }
372
373     private static NodeConnector fromNodeConnectorRef(Uri uri, Node node) {
374         NodeConnector nodeConnector = null;
375         try {
376             nodeConnector = new NodeConnector(NodeMapping.MD_SAL_TYPE,node.getNodeIDString()+":"+uri.getValue(),node);
377         } catch (ConstructionException e) {
378             e.printStackTrace();
379         }
380         return nodeConnector;
381     }
382
383     public static Match toMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match source) {
384         Match target = new Match();
385         if (source != null) {
386             fillFrom(target, source.getVlanMatch());
387             fillFrom(target, source.getEthernetMatch());
388             fillFrom(target, source.getLayer3Match());
389             fillFrom(target, source.getLayer4Match());
390             fillFrom(target, source.getIpMatch());
391         }
392
393         return target;
394     }
395
396     private static void fillFrom(Match target, VlanMatch vlanMatch) {
397         if (vlanMatch != null) {
398             VlanId vlanId = vlanMatch.getVlanId();
399             if (vlanId != null) {
400                 org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanIdInner = vlanId
401                         .getVlanId();
402                 if (vlanIdInner != null) {
403                     Integer vlanValue = vlanIdInner.getValue();
404                     if (vlanValue != null) {
405                         target.setField(DL_VLAN, vlanValue.shortValue());
406                     }
407                 }
408             }
409             VlanPcp vlanPcp = vlanMatch.getVlanPcp();
410             if (vlanPcp != null) {
411                 Short vlanPcpValue = vlanPcp.getValue();
412                 if (vlanPcpValue != null) {
413                     target.setField(DL_VLAN_PR, vlanPcpValue.byteValue());
414                 }
415             }
416         }
417     }
418
419     private static void fillFrom(Match target, IpMatch ipMatch) {
420         if (ipMatch != null) {
421             Short ipProtocol = ipMatch.getIpProtocol();
422
423             if (ipProtocol != null && target.getField(NW_PROTO) == null) {
424                 target.setField(NW_PROTO, ipProtocol.byteValue());
425             }
426             Dscp dscp = ipMatch.getIpDscp();
427             if (dscp != null) {
428                 Short dscpValue = dscp.getValue();
429                 if (dscpValue != null) {
430                     target.setField(NW_TOS, dscpValue.byteValue());
431                 }
432             }
433         }
434     }
435
436     private static void fillFrom(Match target, Layer4Match layer4Match) {
437         if (layer4Match == null) {
438             return;
439         }
440         if (layer4Match instanceof SctpMatch) {
441             fillTransportLayer(target, (SctpMatch) layer4Match);
442         } else if (layer4Match instanceof TcpMatch) {
443             fillTransportLayer(target, (TcpMatch) layer4Match);
444         } else if (layer4Match instanceof UdpMatch) {
445             fillTransportLayer(target, (UdpMatch) layer4Match);
446         }
447     }
448
449     private static void fillTransportLayer(Match target, UdpMatch source) {
450         PortNumber udpSourcePort = source.getUdpSourcePort();
451         if (udpSourcePort != null) {
452             Integer udpSourcePortValue = udpSourcePort.getValue();
453             if (udpSourcePortValue != null) {
454                 target.setField(TP_SRC, udpSourcePortValue.shortValue());
455             }
456         }
457
458         PortNumber udpDestPort = source.getUdpDestinationPort();
459         if (udpDestPort != null) {
460             Integer udpDestPortValue = udpDestPort.getValue();
461             if (udpDestPortValue != null) {
462                 target.setField(TP_DST, udpDestPortValue.shortValue());
463             }
464         }
465
466         target.setField(NW_PROTO, UDP);
467     }
468
469     private static void fillTransportLayer(Match target, TcpMatch source) {
470         PortNumber tcpSourcePort = source.getTcpSourcePort();
471         if (tcpSourcePort != null) {
472             Integer tcpSourcePortValue = tcpSourcePort.getValue();
473             if (tcpSourcePortValue != null) {
474                 target.setField(TP_SRC, tcpSourcePortValue.shortValue());
475             }
476         }
477
478         PortNumber tcpDestPort = source.getTcpDestinationPort();
479         if (tcpDestPort != null) {
480             Integer tcpDestPortValue = tcpDestPort.getValue();
481             if (tcpDestPortValue != null) {
482                 target.setField(TP_DST, tcpDestPortValue.shortValue());
483             }
484         }
485
486         target.setField(NW_PROTO, TCP);
487     }
488
489     private static void fillTransportLayer(Match target, SctpMatch source) {
490         PortNumber sctpSourcePort = source.getSctpSourcePort();
491         if (sctpSourcePort != null) {
492             Integer sctpSourcePortValue = sctpSourcePort.getValue();
493             if (sctpSourcePortValue != null) {
494                 target.setField(TP_SRC, sctpSourcePortValue.shortValue());
495             }
496         }
497         PortNumber sctpDestPort = source.getSctpDestinationPort();
498         if (sctpDestPort != null) {
499             Integer sctpDestPortValue = sctpDestPort.getValue();
500             if (sctpDestPortValue != null) {
501                 target.setField(TP_DST, sctpDestPortValue.shortValue());
502             }
503         }
504
505         target.setField(NW_PROTO, CRUDP);
506
507     }
508
509     private static void fillFrom(Match target, Layer3Match source) {
510         if (source == null)
511             return;
512         if (source instanceof Ipv4Match) {
513             fillFromIpv4(target, (Ipv4Match) source);
514         } else if (source instanceof Ipv6Match) {
515             fillFromIpv6(target, (Ipv6Match) source);
516         } else if (source instanceof ArpMatch) {
517             fillFromArp(target, (ArpMatch) source);
518         }
519     }
520
521     private static void fillFromArp(Match target, ArpMatch source) {
522         Ipv4Prefix sourceAddress = source.getArpSourceTransportAddress();
523         if (sourceAddress != null) {
524             target.setField(NW_SRC, inetAddressFrom(sourceAddress), null);
525         }
526         Ipv4Prefix destAddress = source.getArpTargetTransportAddress();
527         if (destAddress != null) {
528             target.setField(NW_DST, inetAddressFrom(destAddress), null);
529         }
530         ArpSourceHardwareAddress sourceHwAddress = source.getArpSourceHardwareAddress();
531         if (sourceHwAddress != null) {
532             target.setField(DL_SRC, bytesFrom(sourceHwAddress.getAddress()));
533         }
534         ArpTargetHardwareAddress targetHwAddress = source.getArpTargetHardwareAddress();
535         if (targetHwAddress != null) {
536             target.setField(DL_DST, bytesFrom(targetHwAddress.getAddress()));
537         }
538
539         target.setField(DL_TYPE, new Short(ETHERNET_ARP));
540
541     }
542
543     private static void fillFromIpv6(Match target, Ipv6Match source) {
544         Ipv6Prefix sourceAddress = source.getIpv6Source();
545         if (sourceAddress != null) {
546             target.setField(NW_SRC, inetAddressFrom(sourceAddress), null);
547         }
548         Ipv6Prefix destAddress = source.getIpv6Destination();
549         if (destAddress != null) {
550             target.setField(NW_DST, inetAddressFrom(destAddress), null);
551         }
552     }
553
554     private static void fillFromIpv4(Match target, Ipv4Match source) {
555         Ipv4Prefix sourceAddress = source.getIpv4Source();
556         if (sourceAddress != null) {
557             target.setField(NW_SRC, inetAddressFrom(sourceAddress), null);
558         }
559         Ipv4Prefix destAddress = source.getIpv4Destination();
560         if (destAddress != null) {
561             target.setField(NW_DST, inetAddressFrom(destAddress), null);
562         }
563     }
564
565     private static InetAddress inetAddressFrom(Ipv4Prefix source) {
566         if (source != null) {
567             String[] parts = source.getValue().split("/");
568             return InetAddresses.forString(parts[0]);
569         }
570         return null;
571     }
572
573     private static InetAddress inetAddressFrom(Ipv6Prefix source) {
574         if (source != null) {
575             String[] parts = source.getValue().split("/");
576             return InetAddresses.forString(parts[0]);
577         }
578         return null;
579     }
580
581     private static void fillFrom(Match target, EthernetMatch source) {
582         if (source == null)
583             return;
584         EthernetType ethType = source.getEthernetType();
585         if (ethType != null) {
586             EtherType ethInnerType = ethType.getType();
587             if (ethInnerType != null && target.getField(DL_TYPE) == null) {
588                 Long value = ethInnerType.getValue();
589                 target.setField(DL_TYPE, value.shortValue());
590             }
591         }
592
593         MacAddressFilter ethSource = source.getEthernetSource();
594         if (ethSource != null) {
595             target.setField(DL_SRC, bytesFrom(ethSource.getAddress()));
596         }
597
598         MacAddressFilter ethDest = source.getEthernetDestination();
599         if (ethDest != null) {
600             target.setField(DL_DST, bytesFrom(ethDest.getAddress()));
601         }
602     }
603
604     public static byte[] bytesFrom(MacAddress address) {
605         String[] mac = address.getValue().split(":");
606         byte[] macAddress = new byte[6]; // mac.length == 6 bytes
607         for (int i = 0; i < mac.length; i++) {
608             macAddress[i] = Integer.decode("0x" + mac[i]).byteValue();
609         }
610         return macAddress;
611     }
612
613     public static byte[] bytesFromDpid(long dpid) {
614         byte[] mac = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
615
616         for (short i = 0; i < 6; i++) {
617             mac[5 - i] = (byte) dpid;
618             dpid >>= 8;
619         }
620
621         return mac;
622     }
623 }