2 * Copyright (c) 2014 Cisco Systems, 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
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
11 import java.net.Inet4Address;
12 import java.net.InetAddress;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
18 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.ParameterBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.IsRequired;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.Type;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
37 import com.google.common.base.Strings;
38 import com.google.common.collect.ImmutableList;
39 import com.google.common.collect.ImmutableMap;
40 import com.google.common.net.InetAddresses;
43 * Match on the IP address of IP traffic
45 public class IpAddressClassifier extends EtherTypeClassifier {
46 public static final ClassifierDefinitionId ID = new ClassifierDefinitionId("55b83ba4-a741-4d26-91ca-7cd197750a3f");
48 protected static final String SRC_ADDR = "src_addr";
49 protected static final String DST_ADDR = "dst_addr";
50 protected static final ClassifierDefinition DEF = new ClassifierDefinitionBuilder()
52 .setParent(EtherTypeClassifier.ID)
53 .setName(new ClassifierName("ip_address"))
54 .setDescription(new Description("Match on the IP address of IP traffic"))
57 new ParameterBuilder()
58 .setName(new ParameterName(SRC_ADDR))
59 .setDescription(new Description("Source IP prefix to match against."))
60 .setIsRequired(IsRequired.Optional)
63 new ParameterBuilder()
64 .setName(new ParameterName(DST_ADDR))
65 .setDescription(new Description("Destination IP prefix to match against."))
66 .setIsRequired(IsRequired.Optional)
67 .setType(Type.String).build()))
69 private static final Map<String, Object> ipv4 = ImmutableMap.<String, Object> of(TYPE, FlowUtils.IPv4);
70 private static final Map<String, Object> ipv6 = ImmutableMap.<String, Object> of(TYPE, FlowUtils.IPv6);
72 private enum IpAddressContext {
77 public ClassifierDefinitionId getId() {
82 public ClassifierDefinition getClassDef() {
87 public List<MatchBuilder> updateMatch(List<MatchBuilder> matches, Map<String, Object> params) {
88 Object t = params.get(SRC_ADDR);
89 String srcAddr = null;
90 if (t instanceof String) {
93 t = params.get(DST_ADDR);
94 String dstAddr = null;
95 if (t instanceof String) {
98 List<MatchBuilder> r = new ArrayList<>();
99 for (MatchBuilder b : matches) {
100 if (srcAddr != null && dstAddr != null) {
101 boolean isSrcIpv4Addr = isIpv4Address(srcAddr);
102 boolean isDstIpv4Addr = isIpv4Address(dstAddr);
103 if (isSrcIpv4Addr != isDstIpv4Addr) {
104 throw new IllegalArgumentException("Ip address [" + srcAddr + "] is not the same version as ["
107 r.addAll(updateMatch(b, srcAddr, dstAddr, getIpVersion(isSrcIpv4Addr)));
108 } else if (srcAddr == null && dstAddr == null) {
109 r.addAll(super.updateMatch(Collections.singletonList(new MatchBuilder(b.build())), ipv4));
110 r.addAll(super.updateMatch(Collections.singletonList(new MatchBuilder(b.build())), ipv6));
112 if (srcAddr != null) {
113 r.addAll(updateMatch(new MatchBuilder(b.build()), srcAddr, null,
114 getIpVersion(isIpv4Address(srcAddr))));
116 r.addAll(updateMatch(new MatchBuilder(b.build()), null, dstAddr,
117 getIpVersion(isIpv4Address(dstAddr))));
124 private List<MatchBuilder> updateMatch(MatchBuilder matchBuilder, String srcAddr, String dstAddr,
125 Map<String, Object> params) {
126 List<MatchBuilder> r = super.updateMatch(Collections.singletonList(matchBuilder), params);
127 Long ipVersion = (Long) params.get(TYPE);
128 for (MatchBuilder mb : r) {
129 Layer3Match l3m = mb.getLayer3Match();
130 l3m = updateIpAddressField(ipVersion, srcAddr, IpAddressContext.SRC, l3m);
131 l3m = updateIpAddressField(ipVersion, dstAddr, IpAddressContext.DST, l3m);
132 mb.setLayer3Match(l3m);
137 private Map<String, Object> getIpVersion(boolean isIpv4) {
138 if (isIpv4 == true) {
144 private boolean isIpv4Address(String cidr) {
145 String[] ipAndPrefix = cidr.split("/");
146 if (ipAndPrefix.length != 2) {
147 throw new IllegalStateException(cidr + " does not match CIDR format.");
149 InetAddress ip = InetAddresses.forString(ipAndPrefix[0]);
150 if (ip instanceof Inet4Address) {
156 private Layer3Match updateIpAddressField(Long ipVersion, String ipAddr, IpAddressContext ctx, Layer3Match l3m) {
157 if (Strings.isNullOrEmpty(ipAddr)) {
160 if (ipVersion.equals(FlowUtils.IPv4)) {
161 l3m = updateIpv4AddressField(ipAddr, ctx, l3m);
162 } else if (ipVersion.equals(FlowUtils.IPv6)) {
163 l3m = updateIpv6AddressField(ipAddr, ctx, l3m);
168 private Layer3Match updateIpv4AddressField(String ipAddr, IpAddressContext ctx, Layer3Match l3match) {
169 Ipv4MatchBuilder ipv4mb;
170 if (l3match == null) {
171 ipv4mb = new Ipv4MatchBuilder();
173 ipv4mb = new Ipv4MatchBuilder((Ipv4Match) l3match);
175 if (ctx.equals(IpAddressContext.SRC)) {
176 return ipv4mb.setIpv4Source(new Ipv4Prefix(ipAddr)).build();
178 return ipv4mb.setIpv4Destination(new Ipv4Prefix(ipAddr)).build();
181 private Layer3Match updateIpv6AddressField(String ipAddr, IpAddressContext ctx, Layer3Match l3match) {
182 Ipv6MatchBuilder ipv6mb;
183 if (l3match == null) {
184 ipv6mb = new Ipv6MatchBuilder();
186 ipv6mb = new Ipv6MatchBuilder((Ipv6Match) l3match);
188 if (ctx.equals(IpAddressContext.SRC)) {
189 return ipv6mb.setIpv6Source(new Ipv6Prefix(ipAddr)).build();
191 return ipv6mb.setIpv6Destination(new Ipv6Prefix(ipAddr)).build();