blob: 49bbcac25fe24ac183709cc860c1bc27bf365a75 [file] [log] [blame]
Jonathan Hart382623d2014-04-03 09:48:11 -07001package net.onrc.onos.apps.bgproute;
pingping-lina2cbfad2013-03-07 08:39:21 +08002
3import java.net.InetAddress;
4import java.net.UnknownHostException;
Jonathan Hart32e18222013-08-07 22:05:42 +12005import java.util.Arrays;
pingping-lina2cbfad2013-03-07 08:39:21 +08006
Jonathan Hartabf10222013-08-13 10:19:34 +12007import com.google.common.net.InetAddresses;
8
pingping-lina2cbfad2013-03-07 08:39:21 +08009public class Prefix {
Jonathan Hart738980f2014-04-04 10:11:15 -070010 private static final int MAX_BYTES = 4;
pingping-lina2cbfad2013-03-07 08:39:21 +080011
Ray Milkey269ffb92014-04-03 14:43:30 -070012 private final int prefixLength;
13 private final byte[] address;
Jonathan Hart61ba9372013-05-19 20:10:29 -070014
Ray Milkey269ffb92014-04-03 14:43:30 -070015 //For verifying the arguments and pretty printing
16 private final InetAddress inetAddress;
Jonathan Hart32e18222013-08-07 22:05:42 +120017
Ray Milkey269ffb92014-04-03 14:43:30 -070018 public Prefix(byte[] addr, int prefixLength) {
19 if (addr == null || addr.length != MAX_BYTES ||
20 prefixLength < 0 || prefixLength > MAX_BYTES * Byte.SIZE) {
21 throw new IllegalArgumentException();
22 }
Jonathan Hart61ba9372013-05-19 20:10:29 -070023
Ray Milkey269ffb92014-04-03 14:43:30 -070024 address = canonicalizeAddress(addr, prefixLength);
25 this.prefixLength = prefixLength;
26
27 try {
28 inetAddress = InetAddress.getByAddress(address);
29 } catch (UnknownHostException e) {
Jonathan Hart738980f2014-04-04 10:11:15 -070030 throw new IllegalArgumentException("Couldn't parse IP address", e);
Ray Milkey269ffb92014-04-03 14:43:30 -070031 }
32 }
33
34 public Prefix(String strAddress, int prefixLength) {
35 byte[] addr = null;
36 addr = InetAddresses.forString(strAddress).getAddress();
37
38 if (addr == null || addr.length != MAX_BYTES ||
39 prefixLength < 0 || prefixLength > MAX_BYTES * Byte.SIZE) {
40 throw new IllegalArgumentException();
41 }
42
43 address = canonicalizeAddress(addr, prefixLength);
44 this.prefixLength = prefixLength;
45
46 try {
47 inetAddress = InetAddress.getByAddress(address);
48 } catch (UnknownHostException e) {
Jonathan Hart738980f2014-04-04 10:11:15 -070049 throw new IllegalArgumentException("Couldn't parse IP address", e);
Ray Milkey269ffb92014-04-03 14:43:30 -070050 }
51 }
52
Ray Milkey5df613b2014-04-15 10:50:56 -070053 private byte[] canonicalizeAddress(byte[] addressValue,
54 int prefixLengthValue) {
55 byte[] result = new byte[addressValue.length];
Ray Milkey269ffb92014-04-03 14:43:30 -070056
Ray Milkey5df613b2014-04-15 10:50:56 -070057 if (prefixLengthValue == 0) {
Ray Milkey269ffb92014-04-03 14:43:30 -070058 for (int i = 0; i < MAX_BYTES; i++) {
59 result[i] = 0;
60 }
61
62 return result;
63 }
64
Ray Milkey5df613b2014-04-15 10:50:56 -070065 result = Arrays.copyOf(addressValue, addressValue.length);
Ray Milkey269ffb92014-04-03 14:43:30 -070066
67 //Set all bytes after the end of the prefix to 0
Ray Milkey5df613b2014-04-15 10:50:56 -070068 int lastByteIndex = (prefixLengthValue - 1) / Byte.SIZE;
Ray Milkey269ffb92014-04-03 14:43:30 -070069 for (int i = lastByteIndex; i < MAX_BYTES; i++) {
70 result[i] = 0;
71 }
72
Ray Milkey5df613b2014-04-15 10:50:56 -070073 byte lastByte = addressValue[lastByteIndex];
Ray Milkey269ffb92014-04-03 14:43:30 -070074 byte mask = 0;
75 byte msb = (byte) 0x80;
Ray Milkey5df613b2014-04-15 10:50:56 -070076 int lastBit = (prefixLengthValue - 1) % Byte.SIZE;
Ray Milkey269ffb92014-04-03 14:43:30 -070077 for (int i = 0; i < Byte.SIZE; i++) {
78 if (i <= lastBit) {
79 mask |= (msb >> i);
80 }
81 }
82
83 result[lastByteIndex] = (byte) (lastByte & mask);
84
85 return result;
86 }
87
88 public int getPrefixLength() {
89 return prefixLength;
90 }
91
92 public byte[] getAddress() {
Jonathan Hartec9ee2e2014-04-08 22:45:44 -070093 return Arrays.copyOf(address, address.length);
Ray Milkey269ffb92014-04-03 14:43:30 -070094 }
95
96 @Override
97 public boolean equals(Object other) {
Jonathan Hart738980f2014-04-04 10:11:15 -070098 if (!(other instanceof Prefix)) {
Ray Milkey269ffb92014-04-03 14:43:30 -070099 return false;
100 }
101
102 Prefix otherPrefix = (Prefix) other;
103
104 return (Arrays.equals(address, otherPrefix.address)) &&
105 (prefixLength == otherPrefix.prefixLength);
106 }
107
108 @Override
109 public int hashCode() {
110 int hash = 17;
111 hash = 31 * hash + prefixLength;
112 hash = 31 * hash + Arrays.hashCode(address);
113 return hash;
114 }
115
116 @Override
117 public String toString() {
118 return inetAddress.getHostAddress() + "/" + prefixLength;
119 }
120
121 public String printAsBits() {
Jonathan Hart738980f2014-04-04 10:11:15 -0700122 StringBuilder result = new StringBuilder();
Ray Milkey269ffb92014-04-03 14:43:30 -0700123 for (int i = 0; i < address.length; i++) {
124 byte b = address[i];
125 for (int j = 0; j < Byte.SIZE; j++) {
126 byte mask = (byte) (0x80 >>> j);
Jonathan Hart738980f2014-04-04 10:11:15 -0700127 result.append(((b & mask) == 0) ? "0" : "1");
Ray Milkey269ffb92014-04-03 14:43:30 -0700128 if (i * Byte.SIZE + j == prefixLength - 1) {
Jonathan Hart738980f2014-04-04 10:11:15 -0700129 return result.toString();
Ray Milkey269ffb92014-04-03 14:43:30 -0700130 }
131 }
Jonathan Hart938a0152014-04-07 18:27:31 -0700132 result.append(' ');
Ray Milkey269ffb92014-04-03 14:43:30 -0700133 }
134 return result.substring(0, result.length() - 1);
135 }
pingping-lina2cbfad2013-03-07 08:39:21 +0800136}