2 * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.aclservice.utils;
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.List;
15 import org.opendaylight.genius.mdsalutil.MatchFieldType;
16 import org.opendaylight.genius.mdsalutil.MatchInfo;
17 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRange;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.SourcePortRange;
28 public class AclServiceOFFlowBuilder {
30 private AclServiceOFFlowBuilder() {
34 * Converts IP matches into flows.
35 * @param matches the matches
36 * @return the map containing the flows and the respective flow id
38 public static Map<String,List<MatchInfoBase>> programIpFlow(Matches matches) {
40 AceIp acl = (AceIp)matches.getAceType();
41 if (acl.getProtocol() == NwConstants.IP_PROT_TCP) {
42 return programTcpFlow(acl);
43 } else if (acl.getProtocol() == NwConstants.IP_PROT_UDP) {
44 return programUdpFlow(acl);
45 } else if (acl.getProtocol() == NwConstants.IP_PROT_ICMP) {
46 return programIcmpFlow(acl);
47 } else if (acl.getProtocol() != -1) {
48 return programOtherProtocolFlow(acl);
54 /** Converts generic protocol matches to flows.
56 * @param acl the access control list
57 * @return the map containing the flows and the respective flow id
59 public static Map<String,List<MatchInfoBase>> programOtherProtocolFlow(AceIp acl) {
60 List<MatchInfoBase> flowMatches = new ArrayList<>();
61 flowMatches.addAll(addSrcIpMatches(acl));
62 flowMatches.addAll(addDstIpMatches(acl));
63 if (acl.getAceIpVersion() instanceof AceIpv4 ) {
64 flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
65 new long[] { NwConstants.ETHTYPE_IPV4 }));
66 } else if (acl.getAceIpVersion() instanceof AceIpv6 ) {
67 flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
68 new long[] { NwConstants.ETHTYPE_IPV6 }));
70 flowMatches.add(new MatchInfo(MatchFieldType.ip_proto,
71 new long[] { acl.getProtocol() }));
72 String flowId = "OTHER_PROTO" + acl.getProtocol();
73 Map<String,List<MatchInfoBase>> flowMatchesMap = new HashMap<>();
74 flowMatchesMap.put(flowId,flowMatches);
75 return flowMatchesMap;
78 /**Converts icmp matches to flows.
79 * @param acl the access control list
80 * @return the map containing the flows and the respective flow id
82 public static Map<String,List<MatchInfoBase>> programIcmpFlow(AceIp acl) {
83 List<MatchInfoBase> flowMatches = new ArrayList<>();
84 flowMatches.addAll(addSrcIpMatches(acl));
85 flowMatches.addAll(addDstIpMatches(acl));
86 //For ICMP port range indicates type and code
87 SourcePortRange sourcePortRange = acl.getSourcePortRange();
88 String flowId = "ICMP_";
89 if (sourcePortRange != null) {
90 if (acl.getAceIpVersion() instanceof AceIpv4 ) {
91 flowMatches.add(new MatchInfo(MatchFieldType.icmp_v4,
92 new long[] { sourcePortRange.getLowerPort().getValue(),
93 sourcePortRange.getUpperPort().getValue() }));
94 flowId = flowId + "V4_SOURCE_" + sourcePortRange.getLowerPort().getValue()
95 + sourcePortRange.getUpperPort().getValue();
96 } else if (acl.getAceIpVersion() instanceof AceIpv6 ) {
97 flowMatches.add(new MatchInfo(MatchFieldType.icmp_v6,
98 new long[] { sourcePortRange.getLowerPort().getValue(),
99 sourcePortRange.getUpperPort().getValue() }));
100 flowId = flowId + "V6_SOURCE_" + sourcePortRange.getLowerPort().getValue() + "_"
101 + sourcePortRange.getUpperPort().getValue() + "_";
104 DestinationPortRange destinationPortRange = acl.getDestinationPortRange();
105 if (destinationPortRange != null) {
106 if (acl.getAceIpVersion() instanceof AceIpv4 ) {
107 flowMatches.add(new MatchInfo(MatchFieldType.icmp_v4,
108 new long[] { destinationPortRange.getLowerPort().getValue(),
109 destinationPortRange.getUpperPort().getValue() }));
110 flowId = flowId + "V4_DESTINATION_" + destinationPortRange.getLowerPort().getValue()
111 + destinationPortRange.getUpperPort().getValue() + "_";
112 } else if (acl.getAceIpVersion() instanceof AceIpv6 ) {
113 flowMatches.add(new MatchInfo(MatchFieldType.icmp_v6,
114 new long[] { destinationPortRange.getLowerPort().getValue(),
115 destinationPortRange.getUpperPort().getValue() }));
116 flowId = flowId + "V6_DESTINATION_" + destinationPortRange.getLowerPort().getValue()
117 + destinationPortRange.getUpperPort().getValue() + "_";
120 flowMatches.add(new MatchInfo(MatchFieldType.ip_proto,
121 new long[] { acl.getProtocol() }));
122 Map<String,List<MatchInfoBase>> flowMatchesMap = new HashMap<>();
123 flowMatchesMap.put(flowId,flowMatches);
124 return flowMatchesMap;
127 /**Converts TCP matches to flows.
128 * @param acl the access control list
129 * @return the map containing the flows and the respective flow id
131 public static Map<String,List<MatchInfoBase>> programTcpFlow(AceIp acl) {
132 Map<String,List<MatchInfoBase>> flowMatchesMap = new HashMap<>();
133 SourcePortRange sourcePortRange = acl.getSourcePortRange();
134 DestinationPortRange destinationPortRange = acl.getDestinationPortRange();
135 if (sourcePortRange == null && destinationPortRange == null) {
136 List<MatchInfoBase> flowMatches = new ArrayList<>();
137 flowMatches.addAll(addSrcIpMatches(acl));
138 flowMatches.addAll(addDstIpMatches(acl));
139 flowMatches.add(new MatchInfo(MatchFieldType.ip_proto,
140 new long[] { acl.getProtocol() }));
141 String flowId = "TCP_SOURCE_ALL_";
142 flowMatchesMap.put(flowId,flowMatches);
143 return flowMatchesMap;
145 if (sourcePortRange != null) {
146 Map<Integer, Integer> portMaskMap = getLayer4MaskForRange(sourcePortRange.getLowerPort().getValue(),
147 sourcePortRange.getUpperPort().getValue());
148 for (Integer port: portMaskMap.keySet()) {
149 List<MatchInfoBase> flowMatches = new ArrayList<>();
150 flowMatches.addAll(addSrcIpMatches(acl));
151 flowMatches.addAll(addDstIpMatches(acl));
152 flowMatches.add(new MatchInfo(MatchFieldType.tcp_src,
153 new long[] { port}));
154 /*flowMatches.add(new NxMatchInfo(NxMatchFieldType.nx_tcp_src_with_mask,
155 new long[] { port, portMaskMap.get(port) }));*/
156 flowMatches.add(new MatchInfo(MatchFieldType.ip_proto,
157 new long[] { acl.getProtocol() }));
158 String flowId = "TCP_SOURCE_" + port + "_" + portMaskMap.get(port);
159 flowMatchesMap.put(flowId,flowMatches);
162 if (destinationPortRange != null) {
163 Map<Integer, Integer> portMaskMap = getLayer4MaskForRange(destinationPortRange.getLowerPort().getValue(),
164 destinationPortRange.getUpperPort().getValue());
165 for (Integer port: portMaskMap.keySet()) {
166 List<MatchInfoBase> flowMatches = new ArrayList<>();
167 flowMatches.addAll(addSrcIpMatches(acl));
168 flowMatches.addAll(addDstIpMatches(acl));
169 flowMatches.add(new MatchInfo(MatchFieldType.tcp_dst,
170 new long[] { port}));
171 /*flowMatches.add(new NxMatchInfo(NxMatchFieldType.nx_tcp_dst_with_mask,
172 new long[] { port, portMaskMap.get(port) }));*/
173 flowMatches.add(new MatchInfo(MatchFieldType.ip_proto,
174 new long[] { acl.getProtocol() }));
175 String flowId = "TCP_DESTINATION_" + port + "_" + portMaskMap.get(port);
176 flowMatchesMap.put(flowId,flowMatches);
179 return flowMatchesMap;
182 /**Converts UDP matches to flows.
183 * @param acl the access control list
184 * @return the map containing the flows and the respective flow id
186 public static Map<String,List<MatchInfoBase>> programUdpFlow(AceIp acl) {
187 Map<String,List<MatchInfoBase>> flowMatchesMap = new HashMap<>();
188 SourcePortRange sourcePortRange = acl.getSourcePortRange();
189 DestinationPortRange destinationPortRange = acl.getDestinationPortRange();
190 if (sourcePortRange == null && destinationPortRange == null) {
191 List<MatchInfoBase> flowMatches = new ArrayList<>();
192 flowMatches.addAll(addSrcIpMatches(acl));
193 flowMatches.addAll(addDstIpMatches(acl));
194 flowMatches.add(new MatchInfo(MatchFieldType.ip_proto,
195 new long[] { acl.getProtocol() }));
196 String flowId = "UDP_SOURCE_ALL_";
197 flowMatchesMap.put(flowId,flowMatches);
198 return flowMatchesMap;
200 if (sourcePortRange != null) {
201 Map<Integer, Integer> portMaskMap = getLayer4MaskForRange(sourcePortRange.getLowerPort().getValue(),
202 sourcePortRange.getUpperPort().getValue());
203 for (Integer port: portMaskMap.keySet()) {
204 List<MatchInfoBase> flowMatches = new ArrayList<>();
205 flowMatches.addAll(addSrcIpMatches(acl));
206 flowMatches.addAll(addDstIpMatches(acl));
207 flowMatches.add(new MatchInfo(MatchFieldType.udp_src,
208 new long[] { port}));
209 /*flowMatches.add(new NxMatchInfo(NxMatchFieldType.nx_udp_src_with_mask,
210 new long[] { port, portMaskMap.get(port) }));*/
211 flowMatches.add(new MatchInfo(MatchFieldType.ip_proto,
212 new long[] { acl.getProtocol() }));
213 String flowId = "UDP_SOURCE_" + port + "_" + portMaskMap.get(port);
214 flowMatchesMap.put(flowId ,flowMatches);
217 if (destinationPortRange != null) {
218 Map<Integer, Integer> portMaskMap = getLayer4MaskForRange(destinationPortRange.getLowerPort().getValue(),
219 destinationPortRange.getUpperPort().getValue());
220 for (Integer port: portMaskMap.keySet()) {
221 List<MatchInfoBase> flowMatches = new ArrayList<>();
222 flowMatches.addAll(addSrcIpMatches(acl));
223 flowMatches.addAll(addDstIpMatches(acl));
224 flowMatches.add(new MatchInfo(MatchFieldType.udp_dst,
225 new long[] { port}));
226 /*flowMatches.add(new NxMatchInfo(NxMatchFieldType.nx_udp_dst_with_mask,
227 new long[] { port, portMaskMap.get(port) }));*/
228 flowMatches.add(new MatchInfo(MatchFieldType.ip_proto,
229 new long[] { acl.getProtocol() }));
230 String flowId = "UDP_DESTINATION_" + port + "_" + portMaskMap.get(port);
231 flowMatchesMap.put(flowId, flowMatches);
235 return flowMatchesMap;
238 /** Adds source ip matches to the flows.
239 * @param acl the access control list
240 * @return the list of flows.
242 public static List<MatchInfoBase> addSrcIpMatches(AceIp acl) {
243 List<MatchInfoBase> flowMatches = new ArrayList<>();
244 if (acl.getAceIpVersion() instanceof AceIpv4 ) {
245 flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
246 new long[] { NwConstants.ETHTYPE_IPV4 }));
247 Ipv4Prefix srcNetwork = ((AceIpv4)acl.getAceIpVersion()).getSourceIpv4Network();
248 if (null != srcNetwork) {
249 String[] ipaddressValues = srcNetwork.getValue().split("/");
250 flowMatches.add(new MatchInfo(MatchFieldType.ipv4_source,
251 new String[] {ipaddressValues[0], ipaddressValues[1]}));
253 } else if (acl.getAceIpVersion() instanceof AceIpv6 ) {
254 flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
255 new long[] { NwConstants.ETHTYPE_IPV6 }));
256 Ipv6Prefix srcNetwork = ((AceIpv6)acl.getAceIpVersion()).getSourceIpv6Network();
257 if (null != srcNetwork) {
264 /** Adds destination ip matches to the flows.
265 * @param acl the access control list
266 * @return the list of flows.
268 public static List<MatchInfoBase> addDstIpMatches(AceIp acl) {
269 List<MatchInfoBase> flowMatches = new ArrayList<>();
270 if (acl.getAceIpVersion() instanceof AceIpv4 ) {
271 flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
272 new long[] { NwConstants.ETHTYPE_IPV4 }));
273 Ipv4Prefix dstNetwork = ((AceIpv4)acl.getAceIpVersion()).getDestinationIpv4Network();
274 if (null != dstNetwork) {
275 String[] ipaddressValues = dstNetwork.getValue().split("/");
276 flowMatches.add(new MatchInfo(MatchFieldType.ipv4_destination,
277 new String[] {ipaddressValues[0], ipaddressValues[1]}));
279 } else if (acl.getAceIpVersion() instanceof AceIpv6 ) {
280 flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
281 new long[] { NwConstants.ETHTYPE_IPV6 }));
282 Ipv6Prefix dstNetwork = ((AceIpv6)acl.getAceIpVersion()).getDestinationIpv6Network();
283 if (null != dstNetwork) {
291 * Converts port range into a set of masked port ranges.
293 * @param portMin the starting port of the range.
294 * @param portMax the ending port of the range.
295 * @return the map containing the port no and their mask.
298 public static Map<Integer,Integer> getLayer4MaskForRange(int portMin, int portMax) {
299 int [] offset = {32768,16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1};
300 int[] mask = {0x8000,0xC000,0xE000,0xF000,0xF800,0xFC00,0xFE00,0xFF00,
301 0xFF80,0xFFC0,0xFFE0,0xFFF0,0xFFF8,0xFFFC,0xFFFE,0xFFFF};
302 int noOfPorts = portMax - portMin + 1;
303 Map<Integer,Integer> portMap = new HashMap<>();
304 if (noOfPorts == 1) {
305 portMap.put(portMin, mask[15]);
308 String binaryNoOfPorts = Integer.toBinaryString(noOfPorts);
309 int medianOffset = 16 - binaryNoOfPorts.length();
310 int medianLength = offset[medianOffset];
312 for (int tempMedian = 0;tempMedian < portMax;) {
313 tempMedian = medianLength + tempMedian;
314 if (portMin < tempMedian) {
320 int currentMedain = median;
321 for (int tempMedianOffset = medianOffset;16 > tempMedianOffset;tempMedianOffset++) {
322 tempMedian = currentMedain - offset[tempMedianOffset];
323 if (portMin <= tempMedian) {
324 for (;portMin <= tempMedian;) {
325 portMap.put(tempMedian, mask[tempMedianOffset]);
326 currentMedain = tempMedian;
327 tempMedian = tempMedian - offset[tempMedianOffset];
331 currentMedain = median;
332 for (int tempMedianOffset = medianOffset;16 > tempMedianOffset;tempMedianOffset++) {
333 tempMedian = currentMedain + offset[tempMedianOffset];
334 if (portMax >= tempMedian - 1) {
335 for (;portMax >= tempMedian - 1;) {
336 portMap.put(currentMedain, mask[tempMedianOffset]);
337 currentMedain = tempMedian;
338 tempMedian = tempMedian + offset[tempMedianOffset];