--- /dev/null
- import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+/*
+ * Copyright (c) 2015 Dell Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.routemgr.net;
+
-
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
++import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.AllocationPools;
- public class IfMgr {
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
- private HashMap<Uuid, VirtualRouter> vrouters;
- private HashMap<Uuid, VirtualSubnet> vsubnets;
- private HashMap<Uuid, VirtualPort> vintfs;
- private HashMap<Uuid, List<VirtualPort>> unprocessedRouterIntfs;
- private HashMap<Uuid, List<VirtualPort>> unprocessedSubnetIntfs;
++public class IfMgr {
+
+ /**
+ * Logger instance.
+ */
+ static final Logger logger = LoggerFactory.getLogger(IfMgr.class);
+
+ // router objects - routers, subnets, interfaces
- this.vrouters = new HashMap<>();
- this.vsubnets = new HashMap<>();
- this.vintfs = new HashMap<>();
++ private HashMap<Uuid, VirtualRouter> vrouters;
++ private HashMap<Uuid, VirtualSubnet> vsubnets;
++ private HashMap<Uuid, VirtualPort> vintfs;
++ private HashMap<Uuid, List<VirtualPort>> unprocessedRouterIntfs;
++ private HashMap<Uuid, List<VirtualPort>> unprocessedSubnetIntfs;
+
+ void init() {
- .setRouterUUID(rtrUuid)
- .setName(rtrName);
++ this.vrouters = new HashMap<>();
++ this.vsubnets = new HashMap<>();
++ this.vintfs = new HashMap<>();
+ this.unprocessedRouterIntfs = new HashMap<>();
+ this.unprocessedSubnetIntfs = new HashMap<>();
+ logger.info("IfMgr is enabled");
+ }
+
++ /**
++ * Add router
++ *
++ * @param rtrUuid router uuid
++ * @param rtrName router name
++ * @param tenantId tenant id
++ * @param isAdminStateUp admin up
++ */
+ public void addRouter(Uuid rtrUuid, String rtrName, Uuid tenantId, Boolean isAdminStateUp) {
+
+ VirtualRouter rtr = new VirtualRouter();
+ if (rtr != null) {
+ rtr.setTenantID(tenantId)
- } else {
++ .setRouterUUID(rtrUuid)
++ .setName(rtrName);
+ vrouters.put(rtrUuid, rtr);
+
+ List<VirtualPort> intfList = unprocessedRouterIntfs.get(rtrUuid);
+
+ for (VirtualPort intf : intfList) {
+ if (intf != null) {
+ intf.setRouter(rtr);
+ rtr.addInterface(intf);
+
+ VirtualSubnet snet = intf.getSubnet();
+ if (snet != null) {
+ snet.setRouter(rtr);
+ }
+ }
+ }
+
+ removeUnprocessed(unprocessedRouterIntfs, rtrUuid);
+
+ } else {
+ logger.error("Create router failed for :{}", rtrUuid);
+ }
+
+ return;
+ }
+
++ /**
++ * Remove Router
++ *
++ * @param rtrUuid router uuid
++ */
+ public void removeRouter(Uuid rtrUuid) {
+
+ VirtualRouter rtr = vrouters.get(rtrUuid);
+ if (rtr != null) {
+ rtr.removeSelf();
+ vrouters.remove(rtrUuid);
+ removeUnprocessed(unprocessedRouterIntfs, rtrUuid);
+ rtr = null;
+ } else {
+ logger.error("Delete router failed for :{}", rtrUuid);
+ }
+ return;
+ }
+
++ /**
++ * Add Subnet
++ *
++ * @param snetId subnet id
++ * @param name subnet name
++ * @param networkId network id
++ * @param tenantId tenant id
++ * @param gatewayIp gateway ip address
++ * @param poolsList pools list
++ */
+ public void addSubnet(Uuid snetId, String name, Uuid networkId, Uuid tenantId,
+ IpAddress gatewayIp, List<AllocationPools> poolsList) {
+
+ VirtualSubnet snet = new VirtualSubnet();
+ if (snet != null) {
+ snet.setTenantID(tenantId)
+ .setSubnetUUID(snetId)
+ .setName(name)
+ .setGatewayIp(gatewayIp);
+
+ // Add address pool
+ for (AllocationPools pool : poolsList) {
+ snet.addPool(pool.getStart(), pool.getEnd());
+ }
+
+ vsubnets.put(snetId, snet);
+
+ List<VirtualPort> intfList = unprocessedSubnetIntfs.get(snetId);
+
+ for (VirtualPort intf : intfList) {
+ if (intf != null) {
+ intf.setSubnet(snet);
+ snet.addInterface(intf);
+
+ VirtualRouter rtr = intf.getRouter();
+ if (rtr != null) {
+ rtr.addSubnet(snet);
+ }
+ }
+ }
+
+ removeUnprocessed(unprocessedSubnetIntfs, snetId);
+
+ } else {
+ logger.error("Create subnet failed for :{}", snetId);
+ }
+ return;
+ }
+
++ /**
++ * Remove Subnet
++ *
++ * @param snetId subnet id
++ */
+ public void removeSubnet(Uuid snetId) {
+
+ VirtualSubnet snet = vsubnets.get(snetId);
+ if (snet != null) {
+ snet.removeSelf();
+ vsubnets.remove(snetId);
+ removeUnprocessed(unprocessedSubnetIntfs, snetId);
+ snet = null;
+ } else {
+ logger.error("Delete subnet failed for :{}", snetId);
+ }
+ return;
+ }
+
+ public void addRouterIntf(Uuid portId, Uuid rtrId, Uuid snetId,
+ Uuid networkId, IpAddress fixedIp, String macAddress) {
+ VirtualPort intf = vintfs.get(portId);
+ if (intf == null) {
+ intf = new VirtualPort();
+ if (intf != null) {
+ vintfs.put(portId, intf);
- } else {
++ } else {
+ logger.error("Create rtr intf failed for :{}", portId);
+ }
+ }
+
+ if (intf != null) {
+ intf.setIntfUUID(portId)
+ .setNodeUUID(rtrId)
+ .setSubnetID(snetId)
+ .setIpAddr(fixedIp)
+ .setNetworkID(networkId)
+ .setMacAddress(macAddress)
+ .setRouterIntfFlag(true);
+
+ VirtualRouter rtr = vrouters.get(rtrId);
+ VirtualSubnet snet = vsubnets.get(snetId);
+
+ if (rtr != null && snet != null) {
+ snet.setRouter(rtr);
+ intf.setSubnet(snet);
+ rtr.addSubnet(snet);
+ } else if (snet != null) {
+ intf.setSubnet(snet);
+ addUnprocessed(unprocessedRouterIntfs, rtrId, intf);
+ } else {
+ addUnprocessed(unprocessedRouterIntfs, rtrId, intf);
+ addUnprocessed(unprocessedSubnetIntfs, snetId, intf);
+ }
+ }
+ return;
+ }
+
+ public void addHostIntf(Uuid portId, Uuid hostId, Uuid snetId,
+ Uuid networkId, IpAddress fixedIp, String macAddress) {
+ VirtualPort intf = vintfs.get(portId);
+ if (intf == null) {
+ intf = new VirtualPort();
+ if (intf != null) {
+ vintfs.put(portId, intf);
- } else {
++ } else {
+ logger.error("Create host intf failed for :{}", portId);
+ }
+ }
+
+ if (intf != null) {
+ intf.setIntfUUID(portId)
+ .setNodeUUID(hostId)
+ .setSubnetID(snetId)
+ .setIpAddr(fixedIp)
+ .setNetworkID(networkId)
+ .setMacAddress(macAddress)
+ .setRouterIntfFlag(false);
+
+ VirtualSubnet snet = vsubnets.get(snetId);
+
+ if (snet != null) {
+ intf.setSubnet(snet);
+ } else {
+ addUnprocessed(unprocessedSubnetIntfs, snetId, intf);
+ }
+ }
+ return;
+ }
+
+ public void updateInterface(Uuid portId, String dpId, Long ofPort) {
+ VirtualPort intf = vintfs.get(portId);
+
+ if (intf == null) {
+ intf = new VirtualPort();
+ if (intf != null) {
+ vintfs.put(portId, intf);
++ } else {
+ logger.error("updateInterface failed for :{}", portId);
+ }
+ }
+
+ if (intf != null) {
+ intf.setDpId(dpId)
+ .setOfPort(ofPort);
+ }
+ return;
+ }
+
+ public void removePort(Uuid portId) {
+ VirtualPort intf = vintfs.get(portId);
+ if (intf != null) {
+ intf.removeSelf();
+ vintfs.remove(portId);
+ intf = null;
+ } else {
+ logger.error("Delete intf failed for :{}", portId);
+ }
+ return;
+ }
+
+ public void deleteInterface(Uuid interfaceUuid, String dpId) {
+ // Nothing to do for now
+ return;
+ }
+
+ public void addUnprocessed(HashMap<Uuid, List<VirtualPort>> unprocessed, Uuid id, VirtualPort intf) {
+
+ List<VirtualPort> intfList = unprocessed.get(id);
+
+ if (intfList == null) {
+ intfList = new ArrayList();
+ intfList.add(intf);
+ unprocessed.put(id, intfList);
+ } else {
+ intfList.add(intf);
+ }
+ return;
+ }
+
+ public void removeUnprocessed(HashMap<Uuid, List<VirtualPort>> unprocessed, Uuid id) {
+
+ List<VirtualPort> intfList = unprocessed.get(id);
+ intfList = null;
+ return;
+ }
+
+}
--- /dev/null
- * @param byte[] data
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.routemgr.utils;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+
+/**
+ * BitBufferHelper class that provides utility methods to
+ * - fetch specific bits from a serialized stream of bits
+ * - convert bits to primitive data type - like short, int, long
+ * - store bits in specified location in stream of bits
+ * - convert primitive data types to stream of bits
+ */
+public class BitBufferHelper {
+ protected static final Logger LOG = LoggerFactory
+ .getLogger(BitBufferHelper.class);
+
+ public static final long BYTE_MASK = 0xFF;
+
+ // Getters
+ // data: array where data are stored
+ // startOffset: bit from where to start reading
+ // numBits: number of bits to read
+ // All this function return an exception if overflow or underflow
+
+ /**
+ * Returns the first byte from the byte array
+ *
- * @param byte[] data
++ * @param data data
+ * @return byte value
+ */
+ public static byte getByte(byte[] data) {
+ if ((data.length * NetUtils.NumBitsInAByte) > Byte.SIZE) {
+ try {
+ throw new BufferException("Container is too small for the number of requested bits");
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ }
+ return (data[0]);
+ }
+
+ /**
+ * Returns the short value for the byte array passed.
+ * Size of byte array is restricted to Short.SIZE
+ *
- * @param byte[] data
++ * @param data data
+ * @return short value
+ */
+ public static short getShort(byte[] data) {
+ if (data.length > Short.SIZE) {
+ try {
+ throw new BufferException("Container is too small for the number of requested bits");
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ }
+ return (short) toNumber(data);
+ }
+
+ /**
+ * Returns the int value for the byte array passed.
+ * Size of byte array is restricted to Integer.SIZE
+ *
- * @param byte[] data
++ * @param data data
+ * @return int - the integer value of byte array
+ */
+ public static int getInt(byte[] data) {
+ if (data.length > Integer.SIZE) {
+ try {
+ throw new BufferException("Container is too small for the number of requested bits");
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ }
+ return (int) toNumber(data);
+ }
+
+ /**
+ * Returns the long value for the byte array passed.
+ * Size of byte array is restricted to Long.SIZE
+ *
- * @param byte[] data
- * @param int - numBits
++ * @param data data
+ * @return long - the integer value of byte array
+ */
+ public static long getLong(byte[] data) {
+ if (data.length > Long.SIZE) {
+ try {
+ throw new BufferException("Container is too small for the number of requested bits");
+ } catch (Exception e) {
+ LOG.error("", e);
+ }
+ }
+ return (long) toNumber(data);
+ }
+
+ /**
+ * Returns the short value for the last numBits of the byte array passed.
+ * Size of numBits is restricted to Short.SIZE
+ *
- * @param byte[] data
- * @param int - numBits
++ * @param data data
++ * @param numBits number of bits
+ * @return short - the short value of byte array
+ */
+ public static short getShort(byte[] data, int numBits) {
+ if (numBits > Short.SIZE) {
+ try {
+ throw new BufferException("Container is too small for the number of requested bits");
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ }
+ int startOffset = data.length * NetUtils.NumBitsInAByte - numBits;
+ byte[] bits = null;
+ try {
+ bits = BitBufferHelper.getBits(data, startOffset, numBits);
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ return (short) toNumber(bits, numBits);
+ }
+
+ /**
+ * Returns the int value for the last numBits of the byte array passed.
+ * Size of numBits is restricted to Integer.SIZE
+ *
- * @param byte[] data
- * @param int - numBits
++ * @param data data
++ * @param numBits number of bits
+ * @return int - the integer value of byte array
+ */
+ public static int getInt(byte[] data, int numBits) {
+ if (numBits > Integer.SIZE) {
+ try {
+ throw new BufferException("Container is too small for the number of requested bits");
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ }
+ int startOffset = data.length * NetUtils.NumBitsInAByte - numBits;
+ byte[] bits = null;
+ try {
+ bits = BitBufferHelper.getBits(data, startOffset, numBits);
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ return (int) toNumber(bits, numBits);
+ }
+
+ /**
+ * Returns the long value for the last numBits of the byte array passed.
+ * Size of numBits is restricted to Long.SIZE
+ *
- * <p/>
++ * @param data data
++ * @param numBits number of bits
+ * @return long - the integer value of byte array
+ */
+ public static long getLong(byte[] data, int numBits) {
+ if (numBits > Long.SIZE) {
+ try {
+ throw new BufferException("Container is too small for the number of requested bits");
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ }
+ if (numBits > data.length * NetUtils.NumBitsInAByte) {
+ try {
+ throw new BufferException("Trying to read more bits than contained in the data buffer");
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ }
+ int startOffset = data.length * NetUtils.NumBitsInAByte - numBits;
+ byte[] bits = null;
+ try {
+ bits = BitBufferHelper.getBits(data, startOffset, numBits);
+ } catch (BufferException e) {
+ LOG.error("", e);
+ }
+ return (long) toNumber(bits, numBits);
+ }
+
+ /**
+ * Reads the specified number of bits from the passed byte array
+ * starting to read from the specified offset
+ * The bits read are stored in a byte array which size is dictated
+ * by the number of bits to be stored.
+ * The bits are stored in the byte array LSB aligned.
- * @param byte[] data
- * @param int startOffset - offset to start fetching bits from data from
- * @param int numBits - number of bits to be fetched from data
++ *
+ * Ex.
+ * Read 7 bits at offset 10
+ * 0 9 10 16 17
+ * 0101000010 | 0000101 | 1111001010010101011
+ * will be returned as {0,0,0,0,0,1,0,1}
+ *
- bytes[ival] = (byte) (valfromcurr << (extraOffsetBits)
- | (valfromnext >> (NetUtils.NumBitsInAByte - extraOffsetBits)));
++ * @param data data
++ * @param startOffset offset to start fetching bits from data from
++ * @param numBits number of bits to be fetched from data
+ * @return byte [] - LSB aligned bits
+ * @throws BufferException when the startOffset and numBits parameters are not congruent
+ * with the data buffer size
+ */
+ public static byte[] getBits(byte[] data, int startOffset, int numBits)
+ throws BufferException {
+
+ int startByteOffset = 0;
+ int valfromcurr;
+ int valfromnext;
+ int extranumBits = numBits % NetUtils.NumBitsInAByte;
+ int extraOffsetBits = startOffset % NetUtils.NumBitsInAByte;
+ int numBytes = (numBits % NetUtils.NumBitsInAByte != 0) ? 1 + numBits
+ / NetUtils.NumBitsInAByte : numBits / NetUtils.NumBitsInAByte;
+ byte[] shiftedBytes = new byte[numBytes];
+ startByteOffset = startOffset / NetUtils.NumBitsInAByte;
+ byte[] bytes = new byte[numBytes];
+ if (numBits == 0) {
+ return bytes;
+ }
+
+ checkExceptions(data, startOffset, numBits);
+
+ if (extraOffsetBits == 0) {
+ if (extranumBits == 0) {
+ System.arraycopy(data, startByteOffset, bytes, 0, numBytes);
+ return bytes;
+ } else {
+ System.arraycopy(data, startByteOffset, bytes, 0, numBytes - 1);
+ bytes[numBytes - 1] = (byte) ((int) data[startByteOffset
+ + numBytes - 1] & getMSBMask(extranumBits));
+ }
+ } else {
+ int ival;
+ for (ival = 0; ival < numBits / NetUtils.NumBitsInAByte; ival++) {
+ // Reading numBytes starting from offset
+ valfromcurr = (data[startByteOffset + ival])
+ & getLSBMask(NetUtils.NumBitsInAByte - extraOffsetBits);
+ valfromnext = (data[startByteOffset + ival + 1])
+ & getMSBMask(extraOffsetBits);
- | (valfromnext >> (NetUtils.NumBitsInAByte - extraOffsetBits)));
++ bytes[ival] = (byte) (valfromcurr << (extraOffsetBits)
++ | (valfromnext >> (NetUtils.NumBitsInAByte - extraOffsetBits)));
+ }
+ // Now adding the rest of the bits if any
+ if (extranumBits != 0) {
+ if (extranumBits < (NetUtils.NumBitsInAByte - extraOffsetBits)) {
+ valfromnext = (byte) (data[startByteOffset + ival]
+ & ((getMSBMask(extranumBits)) >> extraOffsetBits));
+ bytes[ival] = (byte) (valfromnext << extraOffsetBits);
+ } else if (extranumBits == (NetUtils.NumBitsInAByte - extraOffsetBits)) {
+ valfromcurr = (data[startByteOffset + ival])
+ & getLSBMask(NetUtils.NumBitsInAByte
+ - extraOffsetBits);
+ bytes[ival] = (byte) (valfromcurr << extraOffsetBits);
+ } else {
+ valfromcurr = (data[startByteOffset + ival])
+ & getLSBMask(NetUtils.NumBitsInAByte
+ - extraOffsetBits);
+ valfromnext = (data[startByteOffset + ival + 1])
+ & (getMSBMask(extranumBits
+ - (NetUtils.NumBitsInAByte - extraOffsetBits)));
+ bytes[ival] = (byte) (valfromcurr << (extraOffsetBits)
- * @param byte[] - data to set the input byte
- * @param byte - input byte to be inserted
- * @param startOffset - offset of data[] to start inserting byte from
- * @param numBits - number of bits of input to be inserted into data[]
++ | (valfromnext >> (NetUtils.NumBitsInAByte - extraOffsetBits)));
+ }
+
+ }
+ }
+ // Aligns the bits to LSB
+ shiftedBytes = shiftBitsToLSB(bytes, numBits);
+ return shiftedBytes;
+ }
+
+ // Setters
+ // data: array where data will be stored
+ // input: the data that need to be stored in the data array
+ // startOffset: bit from where to start writing
+ // numBits: number of bits to read
+
+ /**
+ * Bits are expected to be stored in the input byte array from LSB
+ *
- * @param byte[] - data to set the input byte
- * @param byte[] - input bytes to be inserted
- * @param startOffset - offset of data[] to start inserting byte from
- * @param numBits - number of bits of input to be inserted into data[]
- * @return void
++ * @param data data to set the input byte
++ * @param input byte to be inserted
++ * @param startOffset offset of data[] to start inserting byte from
++ * @param numBits number of bits of input to be inserted into data[]
+ * @throws BufferException when the input, startOffset and numBits are not congruent
+ * with the data buffer size
+ */
+ public static void setByte(byte[] data, byte input, int startOffset,
+ int numBits) throws BufferException {
+ byte[] inputByteArray = new byte[1];
+ Arrays.fill(inputByteArray, 0, 1, input);
+ setBytes(data, inputByteArray, startOffset, numBits);
+ }
+
+ /**
+ * Bits are expected to be stored in the input byte array from LSB
+ *
- * @param numBits
- * @return
++ * @param data data to set the input byte
++ * @param input bytes to be inserted
++ * @param startOffset offset of data[] to start inserting byte from
++ * @param numBits number of bits of input to be inserted into data[]
+ * @throws BufferException when the startOffset and numBits parameters are not congruent
+ * with data and input buffers' size
+ */
+ public static void setBytes(byte[] data, byte[] input, int startOffset,
+ int numBits) throws BufferException {
+ checkExceptions(data, startOffset, numBits);
+ insertBits(data, input, startOffset, numBits);
+ }
+
+ /**
+ * Returns numBits 1's in the MSB position
+ *
- * @param numBits
- * @return
++ * @param numBits number of bits
++ * @return numBits 1's in the MSB position
+ */
+ public static int getMSBMask(int numBits) {
+ int mask = 0;
+ for (int ival = 0; ival < numBits; ival++) {
+ mask = mask | (1 << (7 - ival));
+ }
+ return mask;
+ }
+
+ /**
+ * Returns numBits 1's in the LSB position
+ *
- * @param byte[] - array
- * @return long - numerical value of byte array passed
++ * @param numBits number of bits
++ * @return numBits 1's in the LSB position
+ */
+ public static int getLSBMask(int numBits) {
+ int mask = 0;
+ for (int ival = 0; ival < numBits; ival++) {
+ mask = mask | (1 << ival);
+ }
+ return mask;
+ }
+
+ /**
+ * Returns the numerical value of the byte array passed
+ *
- * @param byte[] - array
- * @param int - numBits
- * @return long - numerical value of byte array passed
++ * @param array data array
++ * @return numerical value of byte array passed
+ */
+ public static long toNumber(byte[] array) {
+ long ret = 0;
+ long length = array.length;
+ int value = 0;
+ for (int ival = 0; ival < length; ival++) {
+ value = array[ival];
+ if (value < 0) {
+ value += 256;
+ }
+ ret = ret | (long) ((long) value << ((length - ival - 1) * NetUtils.NumBitsInAByte));
+ }
+ return ret;
+ }
+
+ /**
+ * Returns the numerical value of the last numBits (LSB bits) of the byte
+ * array passed
+ *
- * @param Number
- * @return byte[]
++ * @param array data array
++ * @param numBits number of bits
++ * @return numerical value of byte array passed
+ */
+ public static long toNumber(byte[] array, int numBits) {
+ int length = numBits / NetUtils.NumBitsInAByte;
+ int bitsRest = numBits % NetUtils.NumBitsInAByte;
+ int startOffset = array.length - length;
+ long ret = 0;
+ int value = 0;
+
+ value = array[startOffset - 1] & getLSBMask(bitsRest);
+ value = (array[startOffset - 1] < 0) ? (array[startOffset - 1] + 256)
+ : array[startOffset - 1];
+ ret = ret
+ | (value << ((array.length - startOffset) * NetUtils.NumBitsInAByte));
+
+ for (int ival = startOffset; ival < array.length; ival++) {
+ value = array[ival];
+ if (value < 0) {
+ value += 256;
+ }
+ ret = ret | (long) ((long) value << ((array.length - ival - 1) * NetUtils.NumBitsInAByte));
+ }
+
+ return ret;
+ }
+
+ /**
+ * Accepts a number as input and returns its value in byte form in LSB
+ * aligned form example: input = 5000 [1001110001000] bytes = 19, -120
+ * [00010011] [10001000]
+ *
-
++ * @param input Number as input
++ * @return input value in byte form in LSB aligned
+ */
- * @param Number input
- * @param int numBits - the number of bits to be returned
- * @return byte[]
+ public static byte[] toByteArray(Number input) {
+ Class<? extends Number> dataType = input.getClass();
+ short size = 0;
+ long longValue = input.longValue();
+
+ if (dataType == Byte.class || dataType == byte.class) {
+ size = Byte.SIZE;
+ } else if (dataType == Short.class || dataType == short.class) {
+ size = Short.SIZE;
+ } else if (dataType == Integer.class || dataType == int.class) {
+ size = Integer.SIZE;
+ } else if (dataType == Long.class || dataType == long.class) {
+ size = Long.SIZE;
+ } else {
+ throw new IllegalArgumentException("Parameter must one of the following: Short/Int/Long\n");
+ }
+
+ int length = size / NetUtils.NumBitsInAByte;
+ byte[] bytes = new byte[length];
+
+ // Getting the bytes from input value
+ for (int ival = 0; ival < length; ival++) {
+ bytes[ival] = (byte) ((longValue >> (NetUtils.NumBitsInAByte * (length
+ - ival - 1))) & BYTE_MASK);
+ }
+ return bytes;
+ }
+
+ /**
+ * Accepts a number as input and returns its value in byte form in MSB
+ * aligned form example: input = 5000 [1001110001000] bytes = -114, 64
+ * [10011100] [01000000]
+ *
- * @param numBits
++ * @param input Number as input
++ * @param numBits number of bits
++ * @return input value in byte form in MSB aligned
+ */
+ public static byte[] toByteArray(Number input, int numBits) {
+ Class<? extends Number> dataType = input.getClass();
+ short size = 0;
+ long longValue = input.longValue();
+
+ if (dataType == Short.class) {
+ size = Short.SIZE;
+ } else if (dataType == Integer.class) {
+ size = Integer.SIZE;
+ } else if (dataType == Long.class) {
+ size = Long.SIZE;
+ } else {
+ throw new IllegalArgumentException(
+ "Parameter must one of the following: Short/Int/Long\n");
+ }
+
+ int length = size / NetUtils.NumBitsInAByte;
+ byte[] bytes = new byte[length];
+ byte[] inputbytes = new byte[length];
+ byte[] shiftedBytes;
+
+ // Getting the bytes from input value
+ for (int ival = 0; ival < length; ival++) {
+ bytes[ival] = (byte) ((longValue >> (NetUtils.NumBitsInAByte * (length
+ - ival - 1))) & BYTE_MASK);
+ }
+
+ if ((bytes[0] == 0 && dataType == Long.class)
+ || (bytes[0] == 0 && dataType == Integer.class)) {
+ int index = 0;
+ for (index = 0; index < length; ++index) {
+ if (bytes[index] != 0) {
+ bytes[0] = bytes[index];
+ break;
+ }
+ }
+ System.arraycopy(bytes, index, inputbytes, 0, length - index);
+ Arrays.fill(bytes, length - index + 1, length - 1, (byte) 0);
+ } else {
+ System.arraycopy(bytes, 0, inputbytes, 0, length);
+ }
+
+ shiftedBytes = shiftBitsToMSB(inputbytes, numBits);
+
+ return shiftedBytes;
+ }
+
+ /**
+ * Takes an LSB aligned byte array and returned the LSB numBits in a MSB
+ * aligned byte array
+ *
+ * @param inputbytes
- * <p/>
++ * @param numBits number of bits to be left aligned
+ * @return
+ */
+ /**
+ * It aligns the last numBits bits to the head of the byte array following
+ * them with numBits % 8 zero bits.
- * @param byte[] inputBytes
- * @param int numBits - number of bits to be left aligned
- * @return byte[]
++ *
+ * Example: For inputbytes = [00000111][01110001] and numBits = 12 it
+ * returns: shiftedBytes = [01110111][00010000]
+ *
- numBitstoShiftBy = ((NetUtils.NumBitsInAByte - (numBits % NetUtils.NumBitsInAByte)) < leadZeroesMSB)
++ * @param inputBytes input bytes
++ * @param numBits number of bits to be left aligned
++ * @return numBits bits to the head of the byte array
+ */
+ public static byte[] shiftBitsToMSB(byte[] inputBytes, int numBits) {
+ int numBitstoShiftBy = 0;
+ int leadZeroesMSB = 8;
+ int numEndRestBits = 0;
+ int size = inputBytes.length;
+ byte[] shiftedBytes = new byte[size];
+ int ival;
+
+ for (ival = 0; ival < Byte.SIZE; ival++) {
+ if (((byte) (inputBytes[0] & getMSBMask(ival + 1))) != 0) {
+ leadZeroesMSB = ival;
+ break;
+ }
+ }
+
+ if (numBits % NetUtils.NumBitsInAByte == 0) {
+ numBitstoShiftBy = 0;
+ } else {
- shiftedBytes[ival] = (byte) ((inputBytes[ival] << numBitstoShiftBy)
- | ((inputBytes[ival + 1] & getMSBMask(numBitstoShiftBy))
- >> (numEndRestBits - numBitstoShiftBy)));
++ numBitstoShiftBy = ((NetUtils.NumBitsInAByte - (numBits % NetUtils.NumBitsInAByte)) < leadZeroesMSB)
+ ? (NetUtils.NumBitsInAByte - (numBits % NetUtils.NumBitsInAByte))
+ : leadZeroesMSB;
+ }
+ if (numBitstoShiftBy == 0) {
+ return inputBytes;
+ }
+
+ if (numBits < NetUtils.NumBitsInAByte) {
+ // inputbytes.length = 1 OR read less than a byte
+ shiftedBytes[0] = (byte) ((inputBytes[0] & getLSBMask(numBits)) << numBitstoShiftBy);
+ } else {
+ // # of bits to read from last byte
+ numEndRestBits = NetUtils.NumBitsInAByte
+ - (inputBytes.length * NetUtils.NumBitsInAByte - numBits - numBitstoShiftBy);
+
+ for (ival = 0; ival < (size - 1); ival++) {
+ if ((ival + 1) == (size - 1)) {
+ if (numEndRestBits > numBitstoShiftBy) {
- shiftedBytes[ival] = (byte) ((inputBytes[ival] << numBitstoShiftBy)
- | ((inputBytes[ival + 1] & getMSBMask(numEndRestBits))
- >> (NetUtils.NumBitsInAByte - numEndRestBits)));
++ shiftedBytes[ival] = (byte) ((inputBytes[ival] << numBitstoShiftBy)
++ | ((inputBytes[ival + 1] & getMSBMask(numBitstoShiftBy))
++ >> (numEndRestBits - numBitstoShiftBy)));
+ shiftedBytes[ival + 1] = (byte) ((inputBytes[ival + 1] & getLSBMask(numEndRestBits
+ - numBitstoShiftBy)) << numBitstoShiftBy);
+ } else {
- shiftedBytes[ival] = (byte) ((inputBytes[ival] << numBitstoShiftBy)
- | (inputBytes[ival + 1] & getMSBMask(numBitstoShiftBy))
- >> (NetUtils.NumBitsInAByte - numBitstoShiftBy));
++ shiftedBytes[ival] = (byte) ((inputBytes[ival] << numBitstoShiftBy)
++ | ((inputBytes[ival + 1] & getMSBMask(numEndRestBits))
++ >> (NetUtils.NumBitsInAByte - numEndRestBits)));
+ }
+ }
- * <p/>
++ shiftedBytes[ival] = (byte) ((inputBytes[ival] << numBitstoShiftBy)
++ | (inputBytes[ival + 1] & getMSBMask(numBitstoShiftBy))
++ >> (NetUtils.NumBitsInAByte - numBitstoShiftBy));
+ }
+
+ }
+ return shiftedBytes;
+ }
+
+ /**
+ * It aligns the first numBits bits to the right end of the byte array
+ * preceding them with numBits % 8 zero bits.
- * @param byte[] inputBytes
- * @param int numBits - number of bits to be right aligned
- * @return byte[]
++ *
+ * Example: For inputbytes = [01110111][00010000] and numBits = 12 it
+ * returns: shiftedBytes = [00000111][01110001]
+ *
- shiftedBytes[ival] = (byte) ((inputLsb << numBitstoShift)
- | (inputMsb >> (NetUtils.NumBitsInAByte - numBitstoShift)));
++ * @param inputBytes input bytes
++ * @param numBits number of bits to be right aligned
++ * @return aligns the first numBits bits to the right end of inputBytes
+ */
+ public static byte[] shiftBitsToLSB(byte[] inputBytes, int numBits) {
+ int numBytes = inputBytes.length;
+ int numBitstoShift = numBits % NetUtils.NumBitsInAByte;
+ byte[] shiftedBytes = new byte[numBytes];
+ int inputLsb = 0;
+ int inputMsb = 0;
+
+ if (numBitstoShift == 0) {
+ return inputBytes;
+ }
+
+ for (int ival = 1; ival < numBytes; ival++) {
+ inputLsb = inputBytes[ival - 1]
+ & getLSBMask(NetUtils.NumBitsInAByte - numBitstoShift);
+ inputLsb = (inputLsb < 0) ? (inputLsb + 256) : inputLsb;
+ inputMsb = inputBytes[ival] & getMSBMask(numBitstoShift);
+ inputMsb = (inputBytes[ival] < 0) ? (inputBytes[ival] + 256)
+ : inputBytes[ival];
- * @param byte[] data
- * @param byte[] inputdata
- * @param int startOffset
- * @param int numBits
++ shiftedBytes[ival] = (byte) ((inputLsb << numBitstoShift)
++ | (inputMsb >> (NetUtils.NumBitsInAByte - numBitstoShift)));
+ }
+ inputMsb = inputBytes[0] & (getMSBMask(numBitstoShift));
+ inputMsb = (inputMsb < 0) ? (inputMsb + 256) : inputMsb;
+ shiftedBytes[0] = (byte) (inputMsb >> (NetUtils.NumBitsInAByte - numBitstoShift));
+ return shiftedBytes;
+ }
+
+ /**
+ * Insert in the data buffer at position dictated by the offset the number
+ * of bits specified from the input data byte array. The input byte array
+ * has the bits stored starting from the LSB
+ *
- | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))
++ * @param data data
++ * @param inputdataLSB input data
++ * @param startOffset start offset
++ * @param numBits number of bits
+ */
+ public static void insertBits(byte[] data, byte[] inputdataLSB,
+ int startOffset, int numBits) {
+ byte[] inputdata = shiftBitsToMSB(inputdataLSB, numBits); // Align to
+ // MSB the
+ // passed byte
+ // array
+ int numBytes = numBits / NetUtils.NumBitsInAByte;
+ int startByteOffset = startOffset / NetUtils.NumBitsInAByte;
+ int extraOffsetBits = startOffset % NetUtils.NumBitsInAByte;
+ int extranumBits = numBits % NetUtils.NumBitsInAByte;
+ int restBits = numBits % NetUtils.NumBitsInAByte;
+ int inputMSBbits = 0;
+ int inputLSBbits = 0;
+ int ival;
+
+ if (numBits == 0) {
+ return;
+ }
+
+ if (extraOffsetBits == 0) {
+ if (extranumBits == 0) {
+ numBytes = numBits / NetUtils.NumBitsInAByte;
+ System.arraycopy(inputdata, 0, data, startByteOffset, numBytes);
+ } else {
+ System.arraycopy(inputdata, 0, data, startByteOffset, numBytes);
+ data[startByteOffset + numBytes] = (byte) (data[startByteOffset
+ + numBytes] | (inputdata[numBytes] & getMSBMask(extranumBits)));
+ }
+ } else {
+ for (ival = 0; ival < numBytes; ival++) {
+ if (ival != 0) {
+ inputLSBbits = (inputdata[ival - 1] & getLSBMask(extraOffsetBits));
+ }
+ inputMSBbits = (byte) (inputdata[ival] & (getMSBMask(NetUtils.NumBitsInAByte
+ - extraOffsetBits)));
+ inputMSBbits = (inputMSBbits >= 0) ? inputMSBbits
+ : inputMSBbits + 256;
+ data[startByteOffset + ival] = (byte) (data[startByteOffset + ival]
- | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))
++ | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))
+ | (inputMSBbits >> extraOffsetBits));
+ inputMSBbits = inputLSBbits = 0;
+ }
+ if (restBits < (NetUtils.NumBitsInAByte - extraOffsetBits)) {
+ if (numBytes != 0) {
+ inputLSBbits = (inputdata[ival - 1] & getLSBMask(extraOffsetBits));
+ }
+ inputMSBbits = (byte) (inputdata[ival] & (getMSBMask(restBits)));
+ inputMSBbits = (inputMSBbits >= 0) ? inputMSBbits
+ : inputMSBbits + 256;
+ data[startByteOffset + ival] = (byte) ((data[startByteOffset + ival])
- | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))
++ | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))
+ | (inputMSBbits >> extraOffsetBits));
+ } else if (restBits == (NetUtils.NumBitsInAByte - extraOffsetBits)) {
+ if (numBytes != 0) {
+ inputLSBbits = (inputdata[ival - 1] & getLSBMask(extraOffsetBits));
+ }
+ inputMSBbits = (byte) (inputdata[ival] & (getMSBMask(NetUtils.NumBitsInAByte
+ - extraOffsetBits)));
+ inputMSBbits = (inputMSBbits >= 0) ? inputMSBbits
+ : inputMSBbits + 256;
+ data[startByteOffset + ival] = (byte) (data[startByteOffset + ival]
- | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))
++ | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))
+ | (inputMSBbits >> extraOffsetBits));
+ } else {
+ if (numBytes != 0) {
+ inputLSBbits = (inputdata[ival - 1] & getLSBMask(extraOffsetBits));
+ }
+ inputMSBbits = (byte) (inputdata[ival] & (getMSBMask(NetUtils.NumBitsInAByte
+ - extraOffsetBits)));
+ inputMSBbits = (inputMSBbits >= 0) ? inputMSBbits
+ : inputMSBbits + 256;
+ data[startByteOffset + ival] = (byte) (data[startByteOffset + ival]
- * @param data
- * @param startOffset
- * @param numBits
- * @throws PacketException when the startOffset and numBits parameters
++ | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits))
+ | (inputMSBbits >> extraOffsetBits));
+
+ inputLSBbits = (inputdata[ival] & (getLSBMask(restBits
+ - (NetUtils.NumBitsInAByte - extraOffsetBits)) << (NetUtils.NumBitsInAByte - restBits)));
+ data[startByteOffset + ival + 1] = (byte) (data[startByteOffset
+ + ival + 1] | (inputLSBbits << (NetUtils.NumBitsInAByte - extraOffsetBits)));
+ }
+ }
+ }
+
+ /**
+ * Checks for overflow and underflow exceptions
+ *
++ * @param data data
++ * @param startOffset start offset
++ * @param numBits number of bits
++ * @throws BufferException when the startOffset and numBits parameters
+ * are not congruent with the data buffer's size
+ */
+ public static void checkExceptions(byte[] data, int startOffset, int numBits) throws BufferException {
+ int endOffsetByte;
+ int startByteOffset;
+ endOffsetByte = startOffset
+ / NetUtils.NumBitsInAByte
+ + numBits
+ / NetUtils.NumBitsInAByte
+ + ((numBits % NetUtils.NumBitsInAByte != 0) ? 1 : ((startOffset
+ % NetUtils.NumBitsInAByte != 0) ? 1 : 0));
+ startByteOffset = startOffset / NetUtils.NumBitsInAByte;
+
+ if (data == null) {
+ throw new BufferException("data[] is null\n");
+ }
+
+ if ((startOffset < 0) || (startByteOffset >= data.length) || (endOffsetByte > data.length) || (numBits < 0)
+ || (numBits > NetUtils.NumBitsInAByte * data.length)) {
+ throw new BufferException("Illegal arguement/out of bound exception - data.length = "
+ + data.length + " startOffset = " + startOffset
+ + " numBits " + numBits);
+ }
+ }
+}
--- /dev/null
- * @param i the integer number
+/*
+ * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.routemgr.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility class containing the common utility functions needed for operating on
+ * networking data structures
+ */
+public class NetUtils {
+ protected static final Logger LOG = LoggerFactory.getLogger(NetUtils.class);
+ /**
+ * Constant holding the number of bits in a byte
+ */
+ public static final int NumBitsInAByte = 8;
+
+ /**
+ * Constant holding the number of bytes in MAC Address
+ */
+ public static final int MACAddrLengthInBytes = 6;
+
+ /**
+ * Constant holding the number of words in MAC Address
+ */
+ public static final int MACAddrLengthInWords = 3;
+
+ /**
+ * Constant holding the broadcast MAC address
+ */
+ private static final byte[] BroadcastMACAddr = {-1, -1, -1, -1, -1, -1};
+
+ /**
+ * Converts a 4 bytes array into an integer number
+ *
+ * @param ba the 4 bytes long byte array
+ * @return the integer number
+ */
+ public static int byteArray4ToInt(byte[] ba) {
+ if (ba == null || ba.length != 4) {
+ return 0;
+ }
+ return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 | (0xff & ba[2]) << 8 | (0xff & ba[3]);
+ }
+
+ /**
+ * Converts a 6 bytes array into a long number MAC addresses.
+ *
+ * @param ba The 6 bytes long byte array.
+ * @return The long number.
+ * Zero is returned if {@code ba} is {@code null} or
+ * the length of it is not six.
+ */
+ public static long byteArray6ToLong(byte[] ba) {
+ if (ba == null || ba.length != MACAddrLengthInBytes) {
+ return 0L;
+ }
+ long num = 0L;
+ int ival = 0;
+ do {
+ num <<= NumBitsInAByte;
+ num |= 0xff & ba[ival];
+ ival++;
+ } while (ival < MACAddrLengthInBytes);
+ return num;
+ }
+
+ /**
+ * Converts a long number to a 6 bytes array for MAC addresses.
+ *
+ * @param addr The long number.
+ * @return The byte array.
+ */
+ public static byte[] longToByteArray6(long addr) {
+ byte[] mac = new byte[MACAddrLengthInBytes];
+ int ival = MACAddrLengthInBytes - 1;
+ do {
+ mac[ival] = (byte) addr;
+ addr >>>= NumBitsInAByte;
+ ival--;
+ } while (ival >= 0);
+ return mac;
+ }
+
+ /**
+ * Converts an integer number into a 4 bytes array
+ *
- * @return
++ * @param ival the integer number
+ * @return the byte array
+ */
+ public static byte[] intToByteArray4(int ival) {
+ return new byte[]{(byte) ((ival >> 24) & 0xff), (byte) ((ival >> 16) & 0xff), (byte) ((ival >> 8) & 0xff),
+ (byte) (ival & 0xff)};
+ }
+
+ /**
+ * Converts an IP address passed as integer value into the respective
+ * InetAddress object
+ *
+ * @param address the IP address in integer form
+ * @return the IP address in InetAddress form
+ */
+ public static InetAddress getInetAddress(int address) {
+ InetAddress ip = null;
+ try {
+ ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address));
+ } catch (UnknownHostException e) {
+ LOG.error("", e);
+ }
+ return ip;
+ }
+
+ /**
+ * Return the InetAddress Network Mask given the length of the prefix bit
+ * mask. The prefix bit mask indicates the contiguous leading bits that are
+ * NOT masked out. Example: A prefix bit mask length of 8 will give an
+ * InetAddress Network Mask of 255.0.0.0
+ *
+ * @param prefixMaskLength integer representing the length of the prefix network mask
+ * @param isV6 boolean representing the IP version of the returned address
- * <p/>
++ * @return the inet address
+ */
+ public static InetAddress getInetNetworkMask(int prefixMaskLength, boolean isV6) {
+ if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32) || (isV6 && prefixMaskLength > 128)) {
+ return null;
+ }
+ byte[] v4Address = {0, 0, 0, 0};
+ byte[] v6Address = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ byte[] address = (isV6) ? v6Address : v4Address;
+ int numBytes = prefixMaskLength / 8;
+ int numBits = prefixMaskLength % 8;
+ int ival = 0;
+ for (; ival < numBytes; ival++) {
+ address[ival] = (byte) 0xff;
+ }
+ if (numBits > 0) {
+ int rem = 0;
+ for (int jval = 0; jval < numBits; jval++) {
+ rem |= 1 << (7 - jval);
+ }
+ address[ival] = (byte) rem;
+ }
+
+ try {
+ return InetAddress.getByAddress(address);
+ } catch (UnknownHostException e) {
+ LOG.error("", e);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the prefix size in bits of the specified subnet mask. Example:
+ * For the subnet mask ff.ff.ff.e0 it returns 25 while for ff.00.00.00 it
+ * returns 8. If the passed subnetMask array is null, 0 is returned.
+ *
+ * @param subnetMask the subnet mask as byte array
+ * @return the prefix length as number of bits
+ */
+ public static int getSubnetMaskLength(byte[] subnetMask) {
+ int maskLength = 0;
+ if (subnetMask != null && (subnetMask.length == 4 || subnetMask.length == 16)) {
+ int index = 0;
+ while (index < subnetMask.length && subnetMask[index] == (byte) 0xFF) {
+ maskLength += NetUtils.NumBitsInAByte;
+ index++;
+ }
+ if (index != subnetMask.length) {
+ int bits = NetUtils.NumBitsInAByte - 1;
+ while (bits >= 0 && (subnetMask[index] & 1 << bits) != 0) {
+ bits--;
+ maskLength++;
+ }
+ }
+ }
+ return maskLength;
+ }
+
+ /**
+ * Returns the prefix size in bits of the specified subnet mask. Example:
+ * For the subnet mask 255.255.255.128 it returns 25 while for 255.0.0.0 it
+ * returns 8. If the passed subnetMask object is null, 0 is returned
+ *
+ * @param subnetMask the subnet mask as InetAddress
+ * @return the prefix length as number of bits
+ */
+ public static int getSubnetMaskLength(InetAddress subnetMask) {
+ return subnetMask == null ? 0 : NetUtils.getSubnetMaskLength(subnetMask.getAddress());
+ }
+
+ /**
+ * Given an IP address and a prefix network mask length, it returns the
+ * equivalent subnet prefix IP address Example: for ip = "172.28.30.254" and
+ * maskLen = 25 it will return "172.28.30.128"
+ *
+ * @param ip the IP address in InetAddress form
+ * @param maskLen the length of the prefix network mask
+ * @return the subnet prefix IP address in InetAddress form
+ */
+ public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) {
+ int bytes = maskLen / 8;
+ int bits = maskLen % 8;
+ byte modifiedByte;
+ byte[] sn = ip.getAddress();
+ if (bits > 0) {
+ modifiedByte = (byte) (sn[bytes] >> (8 - bits));
+ sn[bytes] = (byte) (modifiedByte << (8 - bits));
+ bytes++;
+ }
+ for (; bytes < sn.length; bytes++) {
+ sn[bytes] = (byte) (0);
+ }
+ try {
+ return InetAddress.getByAddress(sn);
+ } catch (UnknownHostException excep) {
+ LOG.error("Exception received in getSubnetPrefix", excep.toString());
+ return null;
+ }
+ }
+
+ /**
+ * Checks if the test address and mask conflicts with the filter address and
+ * mask
- * <p/>
++ *
+ * For example:
+ * testAddress: 172.28.2.23
+ * testMask: 255.255.255.0
+ * filterAddress: 172.28.1.10
+ * testMask: 255.255.255.0
+ * do conflict
- * <p/>
++ *
+ * testAddress: 172.28.2.23
+ * testMask: 255.255.255.0
+ * filterAddress: 172.28.1.10
+ * testMask: 255.255.0.0
+ * do not conflict
- * @param testAddress
- * @param filterAddress
- * @param testMask
- * @param filterMask
- * @return
++ *
+ * Null parameters are permitted
+ *
- * @param MACAddress
- * @return
++ * @param testAddress test address
++ * @param filterAddress filter address
++ * @param testMask test mask
++ * @param filterMask filter mask
++ * @return true if there is an address confict
+ */
+ public static boolean inetAddressConflict(InetAddress testAddress, InetAddress filterAddress, InetAddress testMask,
+ InetAddress filterMask) {
+ // Sanity check
+ if ((testAddress == null) || (filterAddress == null)) {
+ return false;
+ }
+
+ // Presence check
+ if (isAny(testAddress) || isAny(filterAddress)) {
+ return false;
+ }
+
+ int testMaskLen = (testMask == null) ? ((testAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
+ .getSubnetMaskLength(testMask);
+ int filterMaskLen = (filterMask == null) ? ((testAddress instanceof Inet4Address) ? 32 : 128) : NetUtils
+ .getSubnetMaskLength(filterMask);
+
+ // Mask length check. Test mask has to be more specific than filter one
+ if (testMaskLen < filterMaskLen) {
+ return true;
+ }
+
+ // Subnet Prefix on filter mask length must be the same
+ InetAddress prefix1 = getSubnetPrefix(testAddress, filterMaskLen);
+ InetAddress prefix2 = getSubnetPrefix(filterAddress, filterMaskLen);
+ return (!prefix1.equals(prefix2));
+ }
+
+ /**
+ * Returns true if the passed MAC address is all zero
+ *
+ * @param mac the byte array representing the MAC address
+ * @return true if all MAC bytes are zero
+ */
+ public static boolean isZeroMAC(byte[] mac) {
+ for (short ival = 0; ival < 6; ival++) {
+ if (mac[ival] != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if the MAC address is the broadcast MAC address and false
+ * otherwise.
+ *
- * @param MACAddress
- * @return
++ * @param macAddress MAC Address
++ * @return true if the MAC address is the broadcast MAC address
+ */
+ public static boolean isBroadcastMACAddr(byte[] macAddress) {
+ if (macAddress.length == MACAddrLengthInBytes) {
+ for (int ival = 0; ival < 6; ival++) {
+ if (macAddress[ival] != BroadcastMACAddr[ival]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the MAC address is a unicast MAC address and false
+ * otherwise.
+ *
- * @param MACAddress
- * @return
++ * @param macAddress MAC Address
++ * @return true if the MAC address is the unicast MAC address
+ */
+ public static boolean isUnicastMACAddr(byte[] macAddress) {
+ if (macAddress.length == MACAddrLengthInBytes) {
+ return (macAddress[0] & 1) == 0;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the MAC address is a multicast MAC address and false
+ * otherwise. Note that this explicitly returns false for the broadcast MAC
+ * address.
+ *
- * @return
++ * @param macAddress MAC Address
++ * @return true if the MAC address is the multicast MAC address
+ */
+ public static boolean isMulticastMACAddr(byte[] macAddress) {
+ if (macAddress.length == MACAddrLengthInBytes && !isBroadcastMACAddr(macAddress)) {
+ return (macAddress[0] & 1) != 0;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the passed InetAddress contains all zero
+ *
+ * @param ip the IP address to test
+ * @return true if the address is all zero
+ */
+ public static boolean isAny(InetAddress ip) {
+ for (byte ival : ip.getAddress()) {
+ if (ival != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean fieldsConflict(int field1, int field2) {
+ if ((field1 == 0) || (field2 == 0) || (field1 == field2)) {
+ return false;
+ }
+ return true;
+ }
+
+ public static InetAddress parseInetAddress(String addressString) {
+ InetAddress address = null;
+ try {
+ address = InetAddress.getByName(addressString);
+ } catch (UnknownHostException excep) {
+ LOG.error("", excep);
+ }
+ return address;
+ }
+
+ /**
+ * Checks if the passed IP v4 address in string form is valid The address
+ * may specify a mask at the end as "/MM"
+ *
+ * @param cidr the v4 address as A.B.C.D/MM
- * @return
++ * @return true if the passed IP v4 address in string form is valid
+ */
+ public static boolean isIPv4AddressValid(String cidr) {
+ if (cidr == null) {
+ return false;
+ }
+
+ String[] values = cidr.split("/");
+ Pattern ipv4Pattern = Pattern
+ .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])");
+ Matcher mm = ipv4Pattern.matcher(values[0]);
+ if (!mm.matches()) {
+ return false;
+ }
+ if (values.length >= 2) {
+ int prefix = Integer.valueOf(values[1]);
+ if ((prefix < 0) || (prefix > 32)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the passed IP v6 address in string form is valid The address
+ * may specify a mask at the end as "/MMM"
+ *
+ * @param cidr the v6 address as A::1/MMM
- * @return
++ * @return true if the passed IP v6 address in string form is valid
+ */
+ public static boolean isIPv6AddressValid(String cidr) {
+ if (cidr == null) {
+ return false;
+ }
+
+ String[] values = cidr.split("/");
+ try {
+ // when given an IP address, InetAddress.getByName validates the ip
+ // address
+ InetAddress addr = InetAddress.getByName(values[0]);
+ if (!(addr instanceof Inet6Address)) {
+ return false;
+ }
+ } catch (UnknownHostException ex) {
+ return false;
+ }
+
+ if (values.length >= 2) {
+ int prefix = Integer.valueOf(values[1]);
+ if ((prefix < 0) || (prefix > 128)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the passed IP address in string form is a valid v4 or v6
+ * address. The address may specify a mask at the end as "/MMM"
+ *
+ * @param cidr the v4 or v6 address as IP/MMM
- * @param b the byte value
++ * @return true if the passed IP address in string form is a valid v4 or v6
+ */
+ public static boolean isIPAddressValid(String cidr) {
+ return NetUtils.isIPv4AddressValid(cidr) || NetUtils.isIPv6AddressValid(cidr);
+ }
+
+ /*
+ * Following utilities are useful when you need to compare or bit shift java
+ * primitive type variable which are inherently signed
+ */
+
+ /**
+ * Returns the unsigned value of the passed byte variable
+ *
- * @param s the short value
++ * @param ival the byte value
+ * @return the int variable containing the unsigned byte value
+ */
+ public static int getUnsignedByte(byte ival) {
+ return ival & 0xFF;
+ }
+
+ /**
+ * Return the unsigned value of the passed short variable
+ *
++ * @param ival the short value
+ * @return the int variable containing the unsigned short value
+ */
+ public static int getUnsignedShort(short ival) {
+ return ival & 0xFFFF;
+ }
+
+ /**
+ * Returns the highest v4 or v6 InetAddress
+ *
+ * @param v6 true for IPv6, false for Ipv4
+ * @return The highest IPv4 or IPv6 address
+ */
+ public static InetAddress gethighestIP(boolean v6) {
+ try {
+ return (v6) ? InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") : InetAddress
+ .getByName("255.255.255.255");
+ } catch (UnknownHostException excep) {
+ LOG.error("Exception received in gethighestIP", excep.toString());
+ return null;
+ }
+ }
+
+ /**
+ * Returns Broadcast MAC Address
+ *
+ * @return the byte array containing broadcast mac address
+ */
+ public static byte[] getBroadcastMACAddr() {
+ return Arrays.copyOf(BroadcastMACAddr, BroadcastMACAddr.length);
+ }
+}