View Javadoc

1   /*
2    * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
3    *
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
7    */
8   package org.opendaylight.lispflowmapping.lisp.util;
9   
10  import com.google.common.base.Preconditions;
11  import com.google.common.net.InetAddresses;
12  
13  import java.net.Inet4Address;
14  import java.net.Inet6Address;
15  import java.net.InetAddress;
16  import java.net.UnknownHostException;
17  import java.nio.ByteBuffer;
18  
19  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IetfInetUtil;
20  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
21  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
22  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.Address;
23  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.InstanceId;
24  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
25  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix;
26  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6;
27  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix;
28  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ServicePath;
29  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
30  import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.source.dest.key.SourceDestKeyBuilder;
31  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  public final class MaskUtil {
36      private static final Logger LOG = LoggerFactory.getLogger(MaskUtil.class);
37      private static final short IPV4_MAX_MASK = 32;
38      private static final short IPV6_MAX_MASK = 128;
39  
40      // Utility class, should not be instantiated
41      private MaskUtil() {
42      }
43  
44      public static boolean isMaskable(Address address) {
45          if (address instanceof Ipv4Prefix || address instanceof Ipv6Prefix || address instanceof SourceDestKey) {
46              return true;
47          } else if (address instanceof InstanceId) {
48              return isMaskable(((InstanceId)address).getInstanceId().getAddress());
49          }
50          return false;
51      }
52  
53      public static boolean isMaskable(SimpleAddress address) {
54          if (address.getIpPrefix() != null) {
55              return true;
56          }
57          return false;
58      }
59  
60      private static final int slashPosition(final String prefix) {
61          final int slash = prefix.lastIndexOf('/');
62          Preconditions.checkArgument(slash >= 0, "Argument %s does not contain a slash", prefix);
63          return slash;
64      }
65  
66      private static String getPrefixAddress(final String prefix) {
67          return prefix.substring(0, slashPosition(prefix));
68      }
69  
70      private static String getPrefixMask(final String prefix) {
71          return prefix.substring(slashPosition(prefix) + 1);
72      }
73  
74      private static String[] splitPrefix(final String prefix) {
75          final int slash = slashPosition(prefix);
76          return new String[] { prefix.substring(0, slash), prefix.substring(slash + 1) };
77      }
78  
79      public static Eid normalize(Eid eid, short mask) {
80          Address address = eid.getAddress();
81          try {
82              if (address instanceof Ipv4Prefix) {
83                  final String addr = getPrefixAddress(((Ipv4Prefix)address).getIpv4Prefix().getValue());
84                  InetAddress normalized = normalizeIP(InetAddresses.forString(addr), mask);
85                  return LispAddressUtil.asIpv4PrefixEid(eid, (Inet4Address)normalized, mask);
86              } else if (address instanceof Ipv6Prefix) {
87                  final String addr = getPrefixAddress(((Ipv6Prefix)address).getIpv6Prefix().getValue());
88                  InetAddress normalized = normalizeIP(InetAddresses.forString(addr), mask);
89                  return LispAddressUtil.asIpv6PrefixEid(eid, (Inet6Address)normalized, mask);
90              } else if (address instanceof InstanceId) {
91                  // TODO - not absolutely necessary, but should be implemented
92                  return eid;
93              }
94          } catch (UnknownHostException e) {
95              LOG.warn("Failed to normalize EID {} with mask {}, returning original EID", eid, mask, e);
96          }
97          return eid;
98      }
99  
100     public static Eid normalize(Eid eid) {
101         Address address = eid.getAddress();
102         try {
103             if (address instanceof Ipv4Prefix) {
104                 String[] v4prefix = splitPrefix(((Ipv4Prefix)address).getIpv4Prefix().getValue());
105                 short mask = Short.parseShort(v4prefix[1]);
106                 InetAddress normalized = normalizeIP(InetAddresses.forString(v4prefix[0]), mask);
107                 return LispAddressUtil.asIpv4PrefixEid(eid, (Inet4Address) normalized, mask);
108             } else if (address instanceof Ipv6Prefix) {
109                 String[] v6prefix = splitPrefix(((Ipv6Prefix)address).getIpv6Prefix().getValue());
110                 short mask = Short.parseShort(v6prefix[1]);
111                 InetAddress normalized = normalizeIP(InetAddresses.forString(v6prefix[0]), mask);
112                 return LispAddressUtil.asIpv6PrefixEid(eid, (Inet6Address) normalized, mask);
113             } else if (address instanceof Ipv4) {
114                 return LispAddressUtil.asIpv4PrefixEid(((Ipv4) address).getIpv4(), eid.getVirtualNetworkId());
115             } else if (address instanceof Ipv6) {
116                 return LispAddressUtil.asIpv6PrefixEid(((Ipv6) address).getIpv6(), eid.getVirtualNetworkId());
117             } else if (address instanceof InstanceId) {
118                 // TODO - not absolutely necessary, but should be implemented
119                 return eid;
120             } else if (address instanceof SourceDestKey) {
121                 return normalizeSrcDst(eid);
122             } else if (address instanceof ServicePath) {
123                 // Build new Service Path eid with service index set to 0
124                 long spi = ((ServicePath) address).getServicePath().getServicePathId().getValue();
125                 long vni = eid.getVirtualNetworkId() != null ? eid.getVirtualNetworkId().getValue() : -1;
126                 return LispAddressUtil.asServicePathEid(vni, spi, (short)0);
127             }
128         } catch (UnknownHostException e) {
129             LOG.warn("Failed to normalize EID {}, returning original", eid, e);
130         }
131         return eid;
132     }
133 
134     private static Eid normalizeSrcDst(Eid eid) throws UnknownHostException {
135         final SimpleAddress normalizedSrc = normalizeSimpleAddress(
136                 ((SourceDestKey) eid.getAddress()).getSourceDestKey().getSource());
137         final SimpleAddress normalizedDst = normalizeSimpleAddress(
138                 ((SourceDestKey) eid.getAddress()).getSourceDestKey().getDest());
139         return LispAddressUtil.asSrcDstEid(new SourceDestKeyBuilder()
140                 .setSource(normalizedSrc).setDest(normalizedDst).build(), eid.getVirtualNetworkId());
141     }
142 
143     private static SimpleAddress normalizeSimpleAddress(SimpleAddress address) throws UnknownHostException {
144         if (address.getIpPrefix() == null) {
145             return address;
146         }
147         return new SimpleAddress(normalizeIpPrefix(address.getIpPrefix()));
148     }
149 
150     private static IpPrefix normalizeIpPrefix(IpPrefix address) throws UnknownHostException {
151         String[] prefix = splitPrefix(String.valueOf(address.getValue()));
152         short mask = Short.parseShort(prefix[1]);
153 
154         InetAddress normalizedAddress = normalizeIP(InetAddresses.forString(prefix[0]), mask);
155         return IetfInetUtil.INSTANCE.ipPrefixFor(normalizedAddress.getAddress(), mask);
156     }
157 
158     private static InetAddress normalizeIP(InetAddress address, int maskLength) throws UnknownHostException {
159         ByteBuffer byteRepresentation = ByteBuffer.wrap(address.getAddress());
160         byte b = (byte) 0xff;
161         int mask = maskLength;
162         for (int i = 0; i < byteRepresentation.array().length; i++) {
163             if (mask >= 8) {
164                 byteRepresentation.put(i, (byte) (b & byteRepresentation.get(i)));
165             } else if (mask > 0) {
166                 byteRepresentation.put(i, (byte) ((byte) (b << (8 - mask)) & byteRepresentation.get(i)));
167             } else {
168                 byteRepresentation.put(i, (byte) (0 & byteRepresentation.get(i)));
169             }
170 
171             mask -= 8;
172         }
173         return InetAddress.getByAddress(byteRepresentation.array());
174     }
175 
176     public static int getMaxMask(Address address) {
177         if (address instanceof Ipv4 || address instanceof Ipv4Prefix) {
178             return IPV4_MAX_MASK;
179         } else if (address instanceof Ipv6 || address instanceof Ipv6Prefix) {
180             return IPV6_MAX_MASK;
181         } else {
182             return -1;
183         }
184     }
185 
186     public static short getMaskForAddress(SimpleAddress address) {
187         if (address.getIpPrefix() == null) {
188             return -1;
189         }
190         return getMaskForIpPrefix(address.getIpPrefix());
191     }
192 
193     private static String getIpPrefixString(IpPrefix prefix) {
194         if (prefix.getIpv4Prefix() != null) {
195             return prefix.getIpv4Prefix().getValue();
196         } else if (prefix.getIpv6Prefix() != null) {
197             return prefix.getIpv6Prefix().getValue();
198         } else {
199             throw new IllegalArgumentException("Invalid prefix " + prefix);
200         }
201     }
202 
203     public static short getMaskForIpPrefix(IpPrefix prefix) {
204         return Short.parseShort(getPrefixMask(getIpPrefixString(prefix)));
205     }
206 
207     public static String getAddressStringForIpPrefix(IpPrefix prefix) {
208         return getPrefixAddress(getIpPrefixString(prefix));
209     }
210 
211     public static String getAddressStringForIpv4Prefix(Ipv4Prefix prefix) {
212         return getPrefixAddress(prefix.getIpv4Prefix().getValue());
213     }
214 
215     public static String getAddressStringForIpv6Prefix(Ipv6Prefix prefix) {
216         return getPrefixAddress(prefix.getIpv6Prefix().getValue());
217     }
218 
219     public static short getMaskForAddress(Address address) {
220         if (address instanceof Ipv4) {
221             return IPV4_MAX_MASK;
222         } else if (address instanceof Ipv6) {
223             return IPV6_MAX_MASK;
224         } else if (address instanceof Ipv4Prefix) {
225             return Short.parseShort(getPrefixMask(((Ipv4Prefix)address).getIpv4Prefix().getValue()));
226         } else if (address instanceof Ipv6Prefix) {
227             return Short.parseShort(getPrefixMask(((Ipv6Prefix)address).getIpv6Prefix().getValue()));
228         } else if (address instanceof InstanceId) {
229             return getMaskForAddress(((InstanceId)address).getInstanceId().getAddress());
230         }
231         return -1;
232     }
233 }