Bug 3540: Implementation of FlowIds based on match data
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / flow / FlowIdUtils.java
1 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
2
3 import com.google.common.base.Joiner;
4 import com.google.common.base.Strings;
5 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
6 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
7 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
8 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.Extension;
9 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow;
11
12 import java.util.Comparator;
13 import java.util.TreeSet;
14
15 public class FlowIdUtils {
16
17     private static final String TABLE_ID_PREFIX = "t";
18     private static final String FLOWID_SEPARATOR = "|";
19     private static final String MATCH_PREFIX = "match[";
20     private static final String MATCH_SUFFIX = "]";
21     private static final String MATCH_SEPARATOR = ", ";
22
23     // *** flow from FlowTable (abstract parent) ***
24
25     /**
26      * For flow without match specified (actually, only "drop all" flow)
27      *
28      * @param prefix String
29      * @return FlowId
30      */
31     public static FlowId newFlowId(String prefix) {
32
33         return new FlowId(prefix);
34     }
35
36     /**
37      * FlowId based on match (with prefix like "t2|localL3|")
38      *
39      * @param tableId Short
40      * @param prefix String
41      * @param match Match
42      * @return FlowId
43      */
44     public static FlowId newFlowId(Short tableId, String prefix, Match match) {
45
46         return new FlowId((tableId != null ? TABLE_ID_PREFIX + tableId + FLOWID_SEPARATOR : "")
47                 + prefix + FLOWID_SEPARATOR
48                 + formatMatch(match));
49     }
50
51     private static String formatMatch(Match match) {
52         StringBuilder builder = new StringBuilder(MATCH_PREFIX);
53         boolean first = true;
54         if (match.getEthernetMatch() != null) {
55             if (first) {
56                 first = false;
57             } else {
58                 builder.append(MATCH_SEPARATOR);
59             }
60             builder.append(match.getEthernetMatch());
61         }
62         if (match.getIcmpv4Match() != null) {
63             if (first) {
64                 first = false;
65             } else {
66                 builder.append(MATCH_SEPARATOR);
67             }
68             builder.append(match.getIcmpv4Match());
69         }
70         if (match.getIcmpv6Match() != null) {
71             if (first) {
72                 first = false;
73             } else {
74                 builder.append(MATCH_SEPARATOR);
75             }
76             builder.append(match.getIcmpv6Match());
77         }
78         if (match.getInPhyPort() != null) {
79             if (first) {
80                 first = false;
81             } else {
82                 builder.append(MATCH_SEPARATOR);
83             }
84             builder.append("inPhyPort=").append(match.getInPhyPort());
85         }
86         if (match.getInPort() != null) {
87             if (first) {
88                 first = false;
89             } else {
90                 builder.append(MATCH_SEPARATOR);
91             }
92             builder.append("inPort=").append(match.getInPort());
93         }
94         if (match.getIpMatch() != null) {
95             if (first) {
96                 first = false;
97             } else {
98                 builder.append(MATCH_SEPARATOR);
99             }
100             builder.append(match.getIpMatch());
101         }
102         if (match.getLayer3Match() != null) {
103             if (first) {
104                 first = false;
105             } else {
106                 builder.append(MATCH_SEPARATOR);
107             }
108             builder.append(match.getLayer3Match());
109         }
110         if (match.getLayer4Match() != null) {
111             if (first) {
112                 first = false;
113             } else {
114                 builder.append(MATCH_SEPARATOR);
115             }
116             builder.append(match.getLayer4Match());
117         }
118         if (match.getMetadata() != null) {
119             if (first) {
120                 first = false;
121             } else {
122                 builder.append(MATCH_SEPARATOR);
123             }
124             builder.append(match.getMetadata());
125         }
126         if (match.getProtocolMatchFields() != null) {
127             if (first) {
128                 first = false;
129             } else {
130                 builder.append(MATCH_SEPARATOR);
131             }
132             builder.append(match.getProtocolMatchFields());
133         }
134         if (match.getTcpFlagMatch() != null) {
135             if (first) {
136                 first = false;
137             } else {
138                 builder.append(MATCH_SEPARATOR);
139             }
140             builder.append(match.getTcpFlagMatch());
141         }
142         if (match.getTunnel() != null) {
143             if (first) {
144                 first = false;
145             } else {
146                 builder.append(MATCH_SEPARATOR);
147             }
148             builder.append(match.getTunnel());
149         }
150         if (match.getVlanMatch() != null) {
151             if (first) {
152                 first = false;
153             } else {
154                 builder.append(MATCH_SEPARATOR);
155             }
156             builder.append(match.getVlanMatch());
157         }
158
159         // only one augmentation is used in Match at the moment;
160         // if in the future there will be more of them, similar handling has to be implemented
161         GeneralAugMatchNodesNodeTableFlow generalAug = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class);
162         if(generalAug != null && generalAug.getExtensionList() != null) {
163             TreeSet<String> extensionAugmentationStrings = new TreeSet<>(new Comparator<String>() {
164                 @Override
165                 public int compare(String a, String b) {
166                     return Strings.nullToEmpty(a).compareTo(Strings.nullToEmpty(b));
167                 }
168             });
169             for (ExtensionList e : generalAug.getExtensionList()) {
170                 Extension ext = e.getExtension();
171                 // only one augmentation is used in Extension at the moment;
172                 // if in the future there will be more of them, similar handling has to be implemented,
173                 // probing augmentations one by one and adding their toString results to our TreeSet
174                 // (and every List<> in them needs to be cast to Set<> to avoid non-equivalence
175                 // due to different element order, and possible element duplication)
176                 NxAugMatchNodesNodeTableFlow nxAug = ext.getAugmentation(NxAugMatchNodesNodeTableFlow.class);
177                 if (nxAug != null) {
178                     extensionAugmentationStrings.add(nxAug.toString());
179                 }
180             }
181
182             if (!first) {
183                 builder.append(MATCH_SEPARATOR);
184             }
185             builder.append("GeneralAugMatchNodesNodeTableFlow[<ExtensionList>=")
186                     .append(Joiner.on(", ").skipNulls().join(extensionAugmentationStrings))
187                     .append(']');
188         }
189         builder.append(MATCH_SUFFIX);
190
191         return builder.toString();
192     }
193
194 }