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