BUG 2302 : odl-clustering-test-app should not be part of the odl-restconf-all feature set
[controller.git] / opendaylight / containermanager / api / src / main / java / org / opendaylight / controller / containermanager / ContainerFlowConfig.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.containermanager;
11
12 import java.io.Serializable;
13 import java.net.Inet4Address;
14 import java.net.Inet6Address;
15 import java.net.InetAddress;
16 import java.net.UnknownHostException;
17 import java.util.ArrayList;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Set;
21
22 import javax.xml.bind.annotation.XmlAccessType;
23 import javax.xml.bind.annotation.XmlAccessorType;
24 import javax.xml.bind.annotation.XmlElement;
25 import javax.xml.bind.annotation.XmlRootElement;
26
27 import org.opendaylight.controller.configuration.ConfigurationObject;
28 import org.opendaylight.controller.sal.match.Match;
29 import org.opendaylight.controller.sal.match.MatchType;
30 import org.opendaylight.controller.sal.packet.BitBufferHelper;
31 import org.opendaylight.controller.sal.utils.IPProtocols;
32 import org.opendaylight.controller.sal.utils.NetUtils;
33 import org.opendaylight.controller.sal.utils.Status;
34 import org.opendaylight.controller.sal.utils.StatusCode;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Flow Specification Java Object for Container Manager
40  * Represents a container flow configuration information for Container Manager.
41  *
42  * Objects of this class are serialized to and de-serialized from binary files through
43  * java serialization API when saving to/reading from Container manager startup
44  * configuration file.
45  */
46 @XmlRootElement (name = "flow-spec-config")
47 @XmlAccessorType(XmlAccessType.NONE)
48 public class ContainerFlowConfig extends ConfigurationObject implements Serializable {
49     private static Logger log = LoggerFactory.getLogger(ContainerFlowConfig.class);
50
51     /** The Constant serialVersionUID. */
52     private static final long serialVersionUID = 1L;
53
54     /** Flow Spec name. */
55     @XmlElement
56     private String name;
57
58     /** The vlan. */
59     @XmlElement
60     private String dlVlan;
61
62     /** The network Source. */
63     @XmlElement
64     private String nwSrc;
65
66     /** The network Destination */
67     @XmlElement
68     private String nwDst;
69
70     /** The protocol. */
71     @XmlElement
72     private String protocol;
73
74     /** The transport source */
75     @XmlElement
76     private String tpSrc;
77
78     /** The transport destination */
79     @XmlElement
80     private String tpDst;
81
82     /* unidirectional flag
83     do not include this flag in equality check
84     @XmlElement */
85     private static boolean unidirectional = false;
86
87
88     /**
89      * Instantiates a new container flow config.
90      */
91     public ContainerFlowConfig() {
92     }
93
94     /**
95      * Instantiates a new container flow config.
96      *
97      * @param name Flow Spec configuration name
98      * @param container Container Name
99      * @param srcIP Source IP Address
100      * @param dstIP Destination IP Address
101      * @param proto Protocol
102      * @param srcPort Source Layer4 Port
103      * @param dstPort Destination Layer4 Port
104      */
105     public ContainerFlowConfig(String name, String srcIP, String dstIP, String proto, String srcPort,
106             String dstPort) {
107         this.name = name;
108         this.dlVlan = null;
109         this.nwSrc = srcIP;
110         this.nwDst = dstIP;
111         this.protocol = proto;
112         this.tpSrc = srcPort;
113         this.tpDst = dstPort;
114         //this.unidirectional = false;
115     }
116
117     public ContainerFlowConfig(String name, String dlVlan, String srcIP, String dstIP, String proto, String srcPort,
118             String dstPort) {
119         this.name = name;
120         this.dlVlan = dlVlan;
121         this.nwSrc = srcIP;
122         this.nwDst = dstIP;
123         this.protocol = proto;
124         this.tpSrc = srcPort;
125         this.tpDst = dstPort;
126     }
127
128
129     public ContainerFlowConfig(ContainerFlowConfig containerFlowConfig) {
130         this.name = containerFlowConfig.name;
131         this.dlVlan = containerFlowConfig.dlVlan;
132         this.nwSrc = containerFlowConfig.nwSrc;
133         this.nwDst = containerFlowConfig.nwDst;
134         this.protocol = containerFlowConfig.protocol;
135         this.tpSrc = containerFlowConfig.tpSrc;
136         this.tpDst = containerFlowConfig.tpDst;
137         //this.unidirectional = containerFlowConfig.unidirectional;
138     }
139
140     /**
141      * Returns the name of this Flow Specification
142      *
143      * @return the name of the Flow Specification
144      */
145     public String getName() {
146         // mandatory field
147         return name;
148     }
149
150     /**
151      * Returns the vlan id.
152      *
153      * @return the Vlan Id
154      */
155     public String getVlan() {
156         return (dlVlan == null || dlVlan.isEmpty()) ? null : dlVlan;
157     }
158
159     /**
160      * Returns the Source IP Address.
161      *
162      * @return the Source IP Address
163      */
164     public String getSrcIP() {
165         return (nwSrc == null || nwSrc.isEmpty()) ? null : nwSrc;
166     }
167
168     /**
169      * Returns the Destination IP Address.
170      *
171      * @return the Destination IP Address
172      */
173     public String getDstIP() {
174         return (nwDst == null || nwDst.isEmpty()) ? null : nwDst;
175     }
176
177     /**
178      * Returns the protocol.
179      *
180      * @return the protocol
181      */
182     public String getProtocol() {
183         return protocol;
184     }
185
186     /**
187      * Returns Source Layer4 Port.
188      *
189      * @return Source Layer4 Port
190      */
191     public String getSrcPort() {
192         return (tpSrc == null || tpSrc.isEmpty()) ? null : tpSrc;
193     }
194
195     /**
196      * Returns Destination Layer4 Port.
197      *
198      * @return Destination Layer4 Port
199      */
200     public String getDstPort() {
201         return (tpDst == null || tpDst.isEmpty()) ? null : tpDst;
202     }
203
204     /*
205      * @return the unidirectional flag
206      */
207     public boolean isUnidirectional() {
208         return unidirectional;
209     }
210
211     /* (non-Javadoc)
212      * @see java.lang.Object#hashCode()
213      */
214     @Override
215     public int hashCode() {
216         final int prime = 31;
217         int result = 1;
218         result = prime * result
219                 + ((protocol == null) ? 0 : protocol.hashCode());
220         result = prime * result + ((name == null) ? 0 : name.hashCode());
221         result = prime * result + ((dlVlan == null) ? 0 : dlVlan.hashCode());
222         result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
223         result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
224         result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
225         result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
226         return result;
227     }
228
229     /*
230      * For comparison, consider that container flow can have empty fields
231      */
232     /* (non-Javadoc)
233      * @see java.lang.Object#equals(java.lang.Object)
234      */
235     @Override
236     public boolean equals(Object obj) {
237         /*
238          * Configuration will be stored in collection only if it is valid
239          * Hence we don't check here for uninitialized fields
240          */
241         if (this == obj) {
242             return true;
243         }
244         if (obj == null) {
245             return false;
246         }
247         if (getClass() != obj.getClass()) {
248             return false;
249         }
250         ContainerFlowConfig other = (ContainerFlowConfig) obj;
251         if (matchName(other) && matchDlVlan(other) && matchSrcIP(other)
252                 && matchDstIP(other) && matchProtocol(other)
253                 && matchSrcPort(other) && matchDstPort(other)) {
254             return true;
255         }
256         return false;
257     }
258
259     /**
260      * Equals by Flow Spec name.
261      *
262      * @param name flow spec name for comparison
263      * @return true, if successful
264      */
265     public boolean equalsByName(String name) {
266         return this.name.equals(name);
267     }
268
269     /**
270      * equalsByMatch
271      *
272      * @param that ContainerFlowConfig for comparison
273      * @return true, if any match is equal
274      */
275     public boolean equalsByMatch(ContainerFlowConfig that) {
276         // get both matches
277         // the match is equal if any of the match is equal
278         List<Match> thisMatch = this.getMatches();
279         List<Match> otherMatch = that.getMatches();
280         // both the lists cannot be null
281         for(Match m1 : thisMatch) {
282             for(Match m2 : otherMatch) {
283                   if(m1.equals(m2)) {
284                     return true;
285                 }
286             }
287         }
288         // if you have reached here without a match
289         // being found
290         // return false
291         return false;
292     }
293
294     /**
295      * Matches the name of this flow spec with that of ContainerFlowConfig parameter's flow spec.
296      *
297      * @param o the ContainerFlowConfig parameter
298      * @return true, if successful
299      */
300     private boolean matchName(ContainerFlowConfig flowSpec) {
301         if (name == flowSpec.name) {
302             return true;
303         }
304         if (name == null || flowSpec.name == null) {
305             return false;
306         }
307         return name.equals(flowSpec.name);
308     }
309
310     /**
311      * Match the set of these vlans with that of flowSpec's vlans.
312      *
313      * @param flowSpec
314      *            Flow Specification
315      * @return true, if successful
316      */
317     private boolean matchDlVlan(ContainerFlowConfig flowSpec) {
318         if (dlVlan == flowSpec.dlVlan) {
319             return true;
320         }
321         if (dlVlan == null || flowSpec.dlVlan == null) {
322             return false;
323         }
324
325         return this.getVlanList().equals(flowSpec.getVlanList());
326     }
327
328     /**
329      * Match Source IP Address.
330      *
331      * @param flowSpec Flow Specification
332      * @return true, if successful
333      */
334     private boolean matchSrcIP(ContainerFlowConfig flowSpec) {
335         if (nwSrc == flowSpec.nwSrc) {
336             return true;
337         }
338         if (nwSrc == null || flowSpec.nwSrc == null) {
339             return false;
340         }
341         return nwSrc.equals(flowSpec.nwSrc);
342     }
343
344     /**
345      * Match Destination IP Address.
346      *
347      * @param flowSpec Flow Specification
348      * @return true, if successful
349      */
350     private boolean matchDstIP(ContainerFlowConfig flowSpec) {
351         if (nwDst == flowSpec.nwDst) {
352             return true;
353         }
354         if (nwDst == null || flowSpec.nwDst == null) {
355             return false;
356         }
357         return this.nwDst.equals(flowSpec.nwDst);
358     }
359
360     /**
361      * Match protocol.
362      *
363      * @param flowSpec Flow Specification
364      * @return true, if successful
365      */
366     private boolean matchProtocol(ContainerFlowConfig flowSpec) {
367         if (protocol == flowSpec.protocol) {
368             return true;
369         }
370         if (protocol == null || flowSpec.protocol == null) {
371             return false;
372         }
373         return this.protocol.equals(flowSpec.protocol);
374     }
375
376     /**
377      * Match Source Layer4 Port.
378      *
379      * @param flowSpec Flow Specification
380      * @return true, if successful
381      */
382     private boolean matchSrcPort(ContainerFlowConfig flowSpec) {
383         if (tpSrc == flowSpec.tpSrc) {
384             return true;
385         }
386         if (tpSrc == null || flowSpec.tpSrc == null) {
387             return false;
388         }
389         return tpSrc.equals(flowSpec.tpSrc);
390     }
391
392     /**
393      * Match Destination Layer4 Port.
394      *
395      * @param flowSpec Flow Specification
396      * @return true, if successful
397      */
398     private boolean matchDstPort(ContainerFlowConfig flowSpec) {
399         if (tpDst == flowSpec.tpDst) {
400             return true;
401         }
402         if (tpDst == null || flowSpec.tpDst == null) {
403             return false;
404         }
405         return this.tpDst.equals(flowSpec.tpDst);
406     }
407
408     /**
409      * Returns the vlan id number for all vlans specified
410      *
411      * @return the vlan id number for all vlans specified
412      */
413     public Set<Short> getVlanList() {
414         /*
415          * example: Vlan = "1,3,5-12"
416          * elemArray = ["1" "3" "5-12"]
417          * elem[2] = "5-12" --> limits = ["5" "12"]
418          * vlanList = [1 3 5 6 7 8 9 10 11 12]
419          */
420         Set<Short> vlanList = new HashSet<Short>();
421         try {
422             String[] elemArray = dlVlan.split(",");
423             for (String elem : elemArray) {
424                 if (elem.contains("-")) {
425                     String[] limits = elem.split("-");
426                     for (short j = Short.valueOf(limits[0]); j <= Short.valueOf(limits[1]); j++) {
427                         vlanList.add(Short.valueOf(j));
428                     }
429                 } else {
430                     vlanList.add(Short.valueOf(elem));
431                 }
432             }
433         } catch (NumberFormatException e) {
434
435         }
436         return vlanList;
437     }
438
439     /**
440      * Returns the Source IP Address mask length.
441      *
442      * @return the Source IP Address mask length
443      */
444     public Short getSrcIPMaskLen() {
445         Short maskLen = 0;
446
447         if (nwSrc != null && !nwSrc.isEmpty()) {
448             String[] s = nwSrc.split("/");
449             if (s.length == 2) {
450                 try {
451                     maskLen = Short.valueOf(s[1]);
452                 } catch (Exception e) {
453                     // no mask or bad mask
454                 }
455             } else {
456                 InetAddress ip = this.getSrcIPNum();
457                 maskLen = (short) ((ip instanceof Inet4Address) ? 32 : 128);
458             }
459         }
460         return maskLen;
461     }
462
463     /**
464      * Returns the Destination IP Address mask length.
465      *
466      * @return the Destination IP Address mask length
467      */
468     public Short getDstIPMaskLen() {
469         Short maskLen = 0;
470         if (nwDst != null && !nwDst.isEmpty()) {
471             String[] s = nwDst.split("/");
472             if (s.length == 2) {
473                 try {
474                     maskLen = Short.valueOf(s[1]);
475                 } catch (Exception e) {
476                     // no mask or bad mask
477                 }
478             } else {
479                 InetAddress ip = this.getDstIPNum();
480                 maskLen = (short) ((ip instanceof Inet4Address) ? 32 : 128);
481             }
482         }
483         return maskLen;
484     }
485
486     /**
487      * Returns the Source IP Address.
488      *
489      * @return the Source IP Address
490      */
491     public InetAddress getSrcIPNum() {
492         InetAddress ip = null;
493         if (nwSrc == null || nwSrc.isEmpty()) {
494             try {
495                 ip = InetAddress.getByAddress(new byte[16]);
496                 return ip;
497             } catch (UnknownHostException e) {
498                 log.error("", e);
499                 return null;
500             }
501         }
502         try {
503             ip = InetAddress.getByName(nwSrc.split("/")[0]);
504         } catch (UnknownHostException e1) {
505             log.error("", e1);
506             return null;
507         }
508         return ip;
509     }
510
511     /**
512      * Returns the Destination IP Address.
513      *
514      * @return the Destination IP Address
515      */
516     public InetAddress getDstIPNum() {
517         InetAddress ip = null;
518         if (nwDst == null || nwDst.isEmpty()) {
519             try {
520                 ip = InetAddress.getByAddress(new byte[16]);
521                 return ip;
522             } catch (UnknownHostException e) {
523                 log.error("",e);
524                 return null;
525             }
526         }
527         try {
528             ip = InetAddress.getByName(nwDst.split("/")[0]);
529         } catch (UnknownHostException e1) {
530             log.error("", e1);
531             return null;
532         }
533         return ip;
534     }
535
536     /**
537      * Returns Source Layer4 Port number.
538      *
539      * @return Source Layer4 Port number
540      */
541     public Short getSrcPortNum() {
542         return (tpSrc == null || tpSrc.isEmpty()) ? Short.valueOf((short) 0)
543                 : Short.valueOf(tpSrc);
544     }
545
546     /**
547      * Returns Destination Layer4 Port number.
548      *
549      * @return Destination Layer4 Port number
550      */
551     public Short getDstPortNum() {
552         return (tpDst == null || tpDst.isEmpty()) ? Short.valueOf((short) 0)
553                 : Short.valueOf(tpDst);
554     }
555
556     /**
557      * Get the IP protocol value
558      *
559      * @return the protocol
560      */
561     public Short getProtoNum() {
562         return protocol == null ? null : IPProtocols.getProtocolNumberShort(protocol);
563     }
564
565     /**
566      * Returns whether this container flow overlap with the passed one This is
567      * true when any two of the resulting matches for the two container flow
568      * configurations intersect.
569      *
570      * @param other
571      *            the other container flow config with which checking the
572      *            overlap
573      * @return true if the two configurations overlap, false otherwise
574      */
575     public boolean overlap(ContainerFlowConfig other) {
576         if (other == null) {
577             return false;
578         }
579         List<Match> myMathes = this.getMatches();
580         List<Match> hisMatches = other.getMatches();
581         for (Match mine : myMathes) {
582             for (Match his : hisMatches) {
583                 if (mine.intersetcs(his)) {
584                     return true;
585                 }
586             }
587         }
588         return false;
589     }
590
591     /**
592      * Checks if this flow specification configuration is valid.
593      *
594      * @return true, if is valid
595      */
596     public Status validate() {
597         if (!isValidResourceName(name)) {
598             return new Status(StatusCode.BADREQUEST, "Invalid name");
599         }
600         Status status = validateVlan();
601         if (!status.isSuccess()) {
602             return status;
603         }
604         status = validateIPs();
605         if (!status.isSuccess()) {
606             return status;
607         }
608         if(!hasValidProtocol()) {
609             return new Status(StatusCode.BADREQUEST, "Invalid IP protocol");
610         }
611         if (!hasValidPorts()) {
612             return new Status(StatusCode.BADREQUEST, "Invalid Source or Destination Port");
613         }
614         if (this.getMatches().get(0).getMatches() == 0) {
615             return new Status(StatusCode.BADREQUEST, "Flow Spec is empty");
616         }
617         return new Status(StatusCode.SUCCESS);
618     }
619
620     /**
621      * Validates the vlan number
622      *
623      * @return the result of the check as Status object
624      */
625     private Status validateVlan() {
626         if (dlVlan != null) {
627             short vlanId = 0;
628             try {
629                 String[] elemArray = dlVlan.split(",");
630                 for (String elem : elemArray) {
631                     if (elem.contains("-")) {
632                         String[] limits = elem.split("-");
633                         if (Short.parseShort(limits[0]) < 0
634                                 || Short.parseShort(limits[0]) >= Short.parseShort(limits[1])
635                                 || Short.parseShort(limits[1]) > 0xfff) {
636                             return new Status(StatusCode.BADREQUEST, "Invalid vlan id");
637                         }
638                     } else {
639                         vlanId = Short.parseShort(elem);
640                         if (vlanId < 0 || vlanId > 0xfff) {
641                             return new Status(StatusCode.BADREQUEST, "Invalid vlan id");
642                         }
643                     }
644                 }
645             } catch (NumberFormatException e) {
646                 return new Status(StatusCode.BADREQUEST, "Invalid vlan id");
647             }
648         }
649         return new Status(StatusCode.SUCCESS);
650     }
651
652     /**
653      * Validates the network addresses, checks syntax and semantic
654      *
655      * @return the result of the check as Status object, if successful
656      */
657     private Status validateIPs() {
658         if (nwSrc != null) {
659             if (!NetUtils.isIPAddressValid(nwSrc)) {
660                 return new Status(StatusCode.BADREQUEST, "Invalid network source address");
661             }
662             byte[] bytePrefix = NetUtils.getSubnetPrefix(this.getSrcIPNum(), this.getSrcIPMaskLen()).getAddress();
663             long prefix = BitBufferHelper.getLong(bytePrefix);
664             if (prefix == 0) {
665                 return new Status(StatusCode.BADREQUEST, "Invalid network source address: subnet zero");
666             }
667         }
668         if (nwDst != null) {
669             if (!NetUtils.isIPAddressValid(nwDst)) {
670                 return new Status(StatusCode.BADREQUEST, "Invalid network destination address");
671             }
672             byte[] bytePrefix = NetUtils.getSubnetPrefix(this.getDstIPNum(), this.getDstIPMaskLen()).getAddress();
673             long prefix = BitBufferHelper.getLong(bytePrefix);
674             if (prefix == 0) {
675                 return new Status(StatusCode.BADREQUEST, "Invalid network destination address: subnet zero");
676             }
677         }
678         return new Status(StatusCode.SUCCESS);
679     }
680
681     /**
682      * Validate the protocol field. Either it can be a enum defined in IPProtocols.java
683      * or a valid IP proto value between 0 and 255, see:
684      * http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
685      * for more details.
686      *
687      * @return true if a valid protocol value
688      */
689     private boolean hasValidProtocol() {
690         IPProtocols p = IPProtocols.fromString(protocol);
691         return p != null;
692     }
693
694     /**
695      *
696      * @param tpPort
697      *               String representing the transport protocol port number
698      * @return true if tpPort contains a decimal value between 0 and 65535
699      */
700     private boolean hasValidPort(String tpPort) {
701         try {
702             int port = Integer.decode(tpPort);
703             return ((port >= 0) && (port <= 0xffff));
704         } catch (NumberFormatException e) {
705             return false;
706         }
707     }
708
709     /**
710      * Validate the transport protocol source and destination ports as
711      * entered by users.
712      *
713      * @return true if ports are defined and are in valid range
714      */
715     private boolean hasValidPorts() {
716         if (tpSrc !=null && !tpSrc.isEmpty()) {
717             if (!hasValidPort(tpSrc)) {
718                 return false;
719             }
720         }
721
722         if (tpDst !=null && !tpDst.isEmpty()) {
723             return hasValidPort(tpDst);
724         }
725         return true;
726     }
727
728     /**
729      * Returns the matches.
730      * If unidirectional flag is set, there will be only one match per vlan in the list
731      * If unidirectional flag is unset there will be two matches per vlan in the list,
732      * only if the specified flow has an intrinsic direction.
733      * For Ex. if the cFlow only has the protocol field configured, no matter
734      * if unidirectional flag is set or not, only one match per vlan will be returned
735      * The client just has to iterate over the returned list
736      * @return the matches
737      */
738     public List<Match> getMatches() {
739         List<Match> matches = new ArrayList<Match>();
740
741         if (this.dlVlan != null && !this.dlVlan.isEmpty()) {
742             for(Short vlan:getVlanList()){
743                 Match match = getMatch(vlan);
744                 matches.add(match);
745             }
746         }
747         else{
748             Match match = getMatch(null);
749             matches.add(match);
750         }
751
752         if (!ContainerFlowConfig.unidirectional) {
753             List<Match> forwardMatches = new ArrayList<Match>(matches);
754             for (Match match : forwardMatches) {
755                 Match reverse = match.reverse();
756                 if (!match.equals(reverse)) {
757                     matches.add(reverse);
758                 }
759             }
760         }
761
762         return matches;
763     }
764
765     private Match getMatch(Short vlan){
766         Match match = new Match();
767
768         if (vlan != null) {
769             match.setField(MatchType.DL_VLAN, vlan);
770         }
771         if (this.nwSrc != null && !this.nwSrc.trim().isEmpty()) {
772             String parts[] = this.nwSrc.split("/");
773             InetAddress ip = NetUtils.parseInetAddress(parts[0]);
774             InetAddress mask = null;
775             int maskLen = 0;
776             if (parts.length > 1) {
777                 maskLen = Integer.parseInt(parts[1]);
778             } else {
779                 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
780             }
781             mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
782             match.setField(MatchType.NW_SRC, ip, mask);
783         }
784         if (this.nwDst != null && !this.nwDst.trim().isEmpty()) {
785             String parts[] = this.nwDst.split("/");
786             InetAddress ip = NetUtils.parseInetAddress(parts[0]);
787             InetAddress mask = null;
788             int maskLen = 0;
789             if (parts.length > 1) {
790                 maskLen = Integer.parseInt(parts[1]);
791             } else {
792                 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
793             }
794             mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
795             match.setField(MatchType.NW_DST, ip, mask);
796         }
797         if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
798             match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
799         }
800         if (this.tpSrc != null && !this.tpSrc.trim().isEmpty()) {
801             match.setField(MatchType.TP_SRC, Integer.valueOf(tpSrc).shortValue());
802         }
803         if (this.tpDst != null && !this.tpDst.trim().isEmpty()) {
804             match.setField(MatchType.TP_DST, Integer.valueOf(tpDst).shortValue());
805         }
806         return match;
807     }
808
809     /*
810      * (non-Javadoc)
811      *
812      * @see java.lang.Object#toString()
813      */
814     @Override
815     public String toString() {
816         return "Container Flow={name:" + name + " dlVlan:" + dlVlan + " nwSrc:" + nwSrc + " nwDst:" + nwDst + " " + "protocol:" + protocol
817                 + " tpSrc:" + tpSrc + " tpDst:" + tpDst + "}";
818     }
819 }