<artifactId>dhcpservice-api</artifactId>
<version>${vpnservices.version}</version>
<packaging>bundle</packaging>
-
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>iana-if-type-2014-05-08</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ </dependencies>
</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.vpnservice.dhcpservice.api;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.BufferException;
+import org.opendaylight.controller.liblldp.HexEncode;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.liblldp.PacketException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants.*;
+
+public class DHCP extends Packet {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(DHCP.class);
+ private static final String OP = "Op";
+ private static final String HTYPE = "Htype";
+ private static final String HLEN = "Hlen";
+ private static final String HOPS = "Hops";
+ private static final String XID = "Xid";
+ private static final String SECS = "Secs";
+ private static final String FLAGS = "Flags";
+ private static final String CIADDR = "Ciaddr";
+ private static final String YIADDR = "Yiaddr";
+ private static final String SIADDR = "Siaddr";
+ private static final String GIADDR = "Giaddr";
+ private static final String CHADDR = "Chaddr";
+ private static final String SNAME = "Sname";
+ private static final String FILE = "File";
+ private static final String MCOOKIE = "Mcookie";
+ private static final String OPTIONS = "Options";
+ private DHCPOptions dhcpOptions = null;
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(OP, new ImmutablePair<Integer, Integer>(0, 8));
+ put(HTYPE, new ImmutablePair<Integer, Integer>(8, 8));
+ put(HLEN, new ImmutablePair<Integer, Integer>(16, 8));
+ put(HOPS, new ImmutablePair<Integer, Integer>(24, 8));
+ put(XID, new ImmutablePair<Integer, Integer>(32, 32));
+ put(SECS, new ImmutablePair<Integer, Integer>(64, 16));
+ put(FLAGS, new ImmutablePair<Integer, Integer>(80, 16));
+ put(CIADDR, new ImmutablePair<Integer, Integer>(96, 32));
+ put(YIADDR, new ImmutablePair<Integer, Integer>(128, 32));
+ put(SIADDR, new ImmutablePair<Integer, Integer>(160, 32));
+ put(GIADDR, new ImmutablePair<Integer, Integer>(192, 32));
+ put(CHADDR, new ImmutablePair<Integer, Integer>(224, 128));
+ put(SNAME, new ImmutablePair<Integer, Integer>(352, 512));
+ put(FILE, new ImmutablePair<Integer, Integer>(864, 1024));
+ put(MCOOKIE, new ImmutablePair<Integer, Integer>(1888, 32));
+ put(OPTIONS, new ImmutablePair<Integer, Integer>(1920, 0));
+ }
+ };
+
+ private final Map<String, byte[]> fieldValues;
+
+ public DHCP() {
+ this(false);
+ }
+
+ public DHCP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ corrupted = false;
+
+ setOp(BOOTREPLY);
+ setHtype(HTYPE_ETHER);
+ setHlen((byte)6);
+ setHops((byte)0);
+ setXid(0);
+ setSecs((short) 0);
+ setFlags((short) 0);
+ setCiaddr(0);
+ setYiaddr(0);
+ setSiaddr(0);
+ setGiaddr(0);
+ setChaddr(new byte[16]);
+ setSname(new byte[64]);
+ setFile(new byte[128]);
+ setMcookie(MAGIC_COOKIE);
+ setOptions(new byte[0]);
+ this.dhcpOptions = new DHCPOptions();
+ }
+
+ //Getters
+ public byte getOp() {
+ return (BitBufferHelper.getByte(fieldValues.get(OP)));
+ }
+
+ public byte getHtype() {
+ return (BitBufferHelper.getByte(fieldValues.get(HTYPE)));
+ }
+
+ public byte getHlen() {
+ return (BitBufferHelper.getByte(fieldValues.get(HLEN)));
+ }
+
+ public byte getHops() {
+ return (BitBufferHelper.getByte(fieldValues.get(HOPS)));
+ }
+
+ public int getXid() {
+ return (BitBufferHelper.getInt(fieldValues.get(XID)));
+ }
+
+ public short getSecs() {
+ return (BitBufferHelper.getShort(fieldValues.get(SECS)));
+ }
+
+ public short getFlags() {
+ return (BitBufferHelper.getShort(fieldValues.get(FLAGS)));
+ }
+
+ public byte[] getCiaddr() {
+ return fieldValues.get(CIADDR);
+ }
+
+ public byte[] getYiaddr() {
+ return fieldValues.get(YIADDR);
+ }
+
+
+ public byte[] getSiaddr() {
+ return fieldValues.get(SIADDR);
+ }
+
+ public InetAddress getSiaddrAsInetAddr() {
+ return DHCPUtils.byteArrayToInetAddr(fieldValues.get(SIADDR));
+ }
+
+ public byte[] getGiaddr() {
+ return fieldValues.get(GIADDR);
+ }
+
+ public byte[] getChaddr() {
+ return fieldValues.get(CHADDR);
+ }
+
+ public byte[] getSname() {
+ return fieldValues.get(SNAME);
+ }
+
+ public byte[] getFile() {
+ return fieldValues.get(FILE);
+ }
+
+ public int getMCookie() {
+ return (BitBufferHelper.getInt(fieldValues.get(MCOOKIE)));
+ }
+
+ public byte[] getOptions() {
+ return fieldValues.get(OPTIONS);
+ }
+
+// TODO:
+// public byte[] getPadding() {
+// return this.pad;
+// }
+
+ // Setters
+ @Override
+ public void setHeaderField(String headerField, byte[] readValue) {
+ if (headerField.equals(OPTIONS) &&
+ (readValue == null || readValue.length == 0)) {
+ hdrFieldsMap.remove(headerField);
+ return;
+ }
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ public DHCP setOp(byte dhcpOp) {
+ byte[] op = BitBufferHelper.toByteArray(dhcpOp);
+ fieldValues.put(OP, op);
+ return this;
+ }
+
+ public DHCP setHtype(byte dhcpHtype) {
+ byte[] htype = BitBufferHelper.toByteArray(dhcpHtype);
+ fieldValues.put(HTYPE, htype);
+ return this;
+ }
+
+ public DHCP setHlen(byte dhcpHlen) {
+ byte[] hlen = BitBufferHelper.toByteArray(dhcpHlen);
+ fieldValues.put(HLEN, hlen);
+ return this;
+ }
+
+ public DHCP setHops(byte dhcpHops ) {
+ byte[] hops = BitBufferHelper.toByteArray(dhcpHops);
+ fieldValues.put(HOPS, hops);
+ return this;
+ }
+
+ public DHCP setXid(int dhcpXid ) {
+ byte[] xid = BitBufferHelper.toByteArray(dhcpXid);
+ fieldValues.put(XID, xid);
+ return this;
+ }
+
+ public DHCP setSecs(short dhcpSecs ) {
+ byte[] secs = BitBufferHelper.toByteArray(dhcpSecs);
+ fieldValues.put(SECS, secs);
+ return this;
+ }
+
+ public DHCP setFlags(short dhcpFlags ) {
+ byte[] flags = BitBufferHelper.toByteArray(dhcpFlags);
+ fieldValues.put(FLAGS, flags);
+ return this;
+ }
+
+ public DHCP setCiaddr(byte[] ciaddr) {
+ fieldValues.put(CIADDR, ciaddr);
+ return this;
+ }
+
+ public DHCP setCiaddr(int dhcpCiaddr ) {
+ byte[] ciaddr = BitBufferHelper.toByteArray(dhcpCiaddr);
+ fieldValues.put(CIADDR, ciaddr);
+ return this;
+ }
+
+ public DHCP setCiaddr(InetAddress dhcpCiaddr ) {
+ byte[] ciaddr = dhcpCiaddr.getAddress();
+ fieldValues.put(CIADDR, ciaddr);
+ return this;
+ }
+
+ public DHCP setCiaddr(String dhcpCiaddr) {
+ byte[] ciaddr = NetUtils.parseInetAddress(dhcpCiaddr).getAddress();
+ fieldValues.put(CIADDR, ciaddr);
+ return this;
+ }
+
+ public DHCP setYiaddr(byte[] yiaddr) {
+ fieldValues.put(YIADDR, yiaddr);
+ return this;
+ }
+
+ public DHCP setYiaddr(int dhcpYiaddr ) {
+ byte[] yiaddr = BitBufferHelper.toByteArray(dhcpYiaddr);
+ fieldValues.put(YIADDR, yiaddr);
+ return this;
+ }
+
+ public DHCP setYiaddr(InetAddress dhcpYiaddr ) {
+ byte[] yiaddr = dhcpYiaddr.getAddress();
+ fieldValues.put(YIADDR, yiaddr);
+ return this;
+ }
+
+ public DHCP setYiaddr(String dhcpYiaddr) {
+ byte[] yiaddr = NetUtils.parseInetAddress(dhcpYiaddr).getAddress();
+ fieldValues.put(YIADDR, yiaddr);
+ return this;
+ }
+
+ public DHCP setSiaddr(byte[] siaddr) {
+ fieldValues.put(SIADDR, siaddr);
+ return this;
+ }
+
+ public DHCP setSiaddr(int dhcpSiaddr ) {
+ byte[] siaddr = BitBufferHelper.toByteArray(dhcpSiaddr);
+ fieldValues.put(SIADDR, siaddr);
+ return this;
+ }
+
+ public DHCP setSiaddr(InetAddress dhcpSiaddr ) {
+ byte[] siaddr = dhcpSiaddr.getAddress();
+ fieldValues.put(SIADDR, siaddr);
+ return this;
+ }
+
+ public DHCP setSiaddr(String dhcpSiaddr) {
+ byte[] siaddr = NetUtils.parseInetAddress(dhcpSiaddr).getAddress();
+ fieldValues.put(SIADDR, siaddr);
+ return this;
+ }
+
+ public DHCP setGiaddr(byte[] giaddr) {
+ fieldValues.put(GIADDR, giaddr);
+ return this;
+ }
+
+ public DHCP setGiaddr(int dhcpGiaddr ) {
+ byte[] giaddr = BitBufferHelper.toByteArray(dhcpGiaddr);
+ fieldValues.put(GIADDR, giaddr);
+ return this;
+ }
+
+ public DHCP setGiaddr(InetAddress dhcpGiaddr ) {
+ byte[] giaddr = dhcpGiaddr.getAddress();
+ fieldValues.put(GIADDR, giaddr);
+ return this;
+ }
+
+ public DHCP setGiaddr(String dhcpGiaddr) {
+ byte[] giaddr = NetUtils.parseInetAddress(dhcpGiaddr).getAddress();
+ fieldValues.put(GIADDR, giaddr);
+ return this;
+ }
+
+ public DHCP setChaddr(byte[] chaddr) {
+ fieldValues.put(CHADDR, chaddr);
+ return this;
+ }
+
+ public DHCP setSname(byte[] sname) {
+ fieldValues.put(SNAME, sname);
+ return this;
+ }
+
+ public DHCP setFile(byte[] file) {
+ fieldValues.put(FILE, file);
+ return this;
+ }
+
+ public DHCP setMcookie(int dhcpMc ) {
+ byte[] mc = BitBufferHelper.toByteArray(dhcpMc);
+ fieldValues.put(MCOOKIE, mc);
+ return this;
+ }
+
+ public DHCP setOptions(byte[] options) {
+ fieldValues.put(OPTIONS, options);
+ return this;
+ }
+
+// public void setPadding(byte[] pad) {
+// this.pad = pad;
+// }
+
+ /**
+ * This method deserializes the data bits obtained from the wire into the
+ * respective header and payload which are of type Packet
+ *
+ * @param data byte[] data from wire to deserialize
+ * @param bitOffset int bit position where packet header starts in data
+ * array
+ * @param size int size of packet in bits
+ * @return Packet
+ * @throws PacketException
+ *
+ * Note: Copied from org.opendaylight.controller.sal.packet.Packet
+ */
+ @Override
+ public Packet deserialize(byte[] data, int bitOffset, int size)
+ throws PacketException {
+
+ // Deserialize the header fields one by one
+ int startOffset = 0, numBits = 0;
+ for (Entry<String, Pair<Integer, Integer>> pairs : hdrFieldCoordMap
+ .entrySet()) {
+ String hdrField = pairs.getKey();
+ startOffset = bitOffset + this.getfieldOffset(hdrField);
+ if(hdrField.equals(OPTIONS)) {
+ numBits = (size - DHCP_NOOPT_HDR_SIZE) * 8;
+ } else {
+ numBits = this.getfieldnumBits(hdrField);
+ }
+ byte[] hdrFieldBytes = null;
+ try {
+ hdrFieldBytes = BitBufferHelper.getBits(data, startOffset,
+ numBits);
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+
+ /*
+ * Store the raw read value, checks the payload type and set the
+ * payloadClass accordingly
+ */
+ this.setHeaderField(hdrField, hdrFieldBytes);
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("{}: {}: {} (offset {} bitsize {})",
+ new Object[] { this.getClass().getSimpleName(), hdrField,
+ HexEncode.bytesToHexString(hdrFieldBytes),
+ startOffset, numBits });
+ }
+ }
+
+ // Deserialize the payload now
+ int payloadStart = startOffset + numBits;
+ int payloadSize = data.length * NetUtils.NumBitsInAByte - payloadStart;
+
+ if (payloadClass != null) {
+ try {
+ payload = payloadClass.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Error parsing payload for Ethernet packet", e);
+ }
+ payload.deserialize(data, payloadStart, payloadSize);
+ payload.setParent(this);
+ } else {
+ /*
+ * The payload class was not set, it means no class for parsing
+ * this payload is present. Let's store the raw payload if any.
+ */
+ int start = payloadStart / NetUtils.NumBitsInAByte;
+ int stop = start + payloadSize / NetUtils.NumBitsInAByte;
+ rawPayload = Arrays.copyOfRange(data, start, stop);
+ }
+ // Take care of computation that can be done only after deserialization
+ postDeserializeCustomOperation(data, payloadStart - getHeaderSize());
+
+ return this;
+ }
+
+ @Override
+ public byte[] serialize() throws PacketException {
+ this.setOptions(this.dhcpOptions.serialize());
+ byte[] data = super.serialize();
+ // Check for OPT_END at end of options
+ if (data.length > DHCP_MAX_SIZE) {
+ // shouldn't have happened
+ // Add exception?
+ logger.error("DHCP Packet too big");
+ } else if (data[data.length - 1] != (byte)255) {
+ // DHCP Options not ended properly
+ //throw new PacketException("Missing DHCP Option END");
+ logger.error("Missing DHCP Option END");
+ }else if(data.length < DHCP_MIN_SIZE) {
+ byte[] padding = new byte[DHCP_MIN_SIZE - data.length];
+ logger.debug("DHCP Pkt too small: {}, padding added {}",
+ data.length, padding.length);
+ data = ArrayUtils.addAll(data, padding);
+ }
+ return data;
+ }
+ @Override
+ /**
+ * Gets the number of bits for the fieldname specified
+ * If the fieldname has variable length like "Options", then this value is computed using the header length
+ * @param fieldname - String
+ * @return number of bits for fieldname - int
+ */
+ public int getfieldnumBits(String fieldName) {
+ if (fieldName.equals(OPTIONS)) {
+ byte[] barr = fieldValues.get(OPTIONS);
+ return (barr.length) * NetUtils.NumBitsInAByte;
+ }
+ return hdrFieldCoordMap.get(fieldName).getRight();
+ }
+
+ @Override
+ public int getHeaderSize() {
+ byte[] barr = fieldValues.get(OPTIONS);
+ int len = 0;
+ if(barr != null) { len = barr.length; }
+ return (DHCP_NOOPT_HDR_SIZE + len) * 8;
+ }
+
+
+ @Override
+ protected void postDeserializeCustomOperation(byte[] data, int startBitOffset) {
+ //TODO: Anything need to be done here?
+ // Check for MAGIC_COOKIE. This means we only support DHCP, not BOOTP
+ int cookie = BitBufferHelper.getInt(fieldValues.get(MCOOKIE));
+ if (cookie != MAGIC_COOKIE) {
+ logger.debug("Not DHCP packet");
+ // Throw exception?
+ }
+ // parse options into DHCPOptions
+ this.dhcpOptions.deserialize(this.getOptions());
+ // reset options byte array, this will also drop padding
+ this.setOptions(this.dhcpOptions.serialize());
+ }
+
+ // Set/get operations for Options
+ public void setMsgType(byte type) {
+ dhcpOptions.setOptionByte(OPT_MESSAGE_TYPE, type);
+ }
+
+ public byte getMsgType() {
+ return dhcpOptions.getOptionByte(OPT_MESSAGE_TYPE);
+ }
+
+ public void setOptionByte(byte code, byte opt) {
+ dhcpOptions.setOptionByte(code, opt);
+ }
+
+ public byte getOptionByte(byte code) {
+ return dhcpOptions.getOptionByte(code);
+ }
+
+ public void setOptionBytes(byte code, byte[] opt) {
+ dhcpOptions.setOption(code, opt);
+ }
+
+ public byte[] getOptionBytes(byte code) {
+ return dhcpOptions.getOptionBytes(code);
+ }
+
+ public void setOptionShort(byte code, short s) {
+ dhcpOptions.setOptionShort(code, s);
+ }
+
+ public short getOptionShort(byte code) {
+ return dhcpOptions.getOptionShort(code);
+ }
+
+ public void setOptionInt(byte code, int i) {
+ dhcpOptions.setOptionInt(code, i);
+ }
+
+ public int getOptionInt(byte code) {
+ return dhcpOptions.getOptionInt(code);
+ }
+
+ public void setOptionInetAddr(byte code, InetAddress addr) {
+ dhcpOptions.setOptionInetAddr(code, addr);
+ }
+
+ public InetAddress getOptionInetAddr(byte code) {
+ return dhcpOptions.getOptionInetAddr(code);
+ }
+
+ public void setOptionInetAddr(byte code, String addr) throws UnknownHostException {
+ dhcpOptions.setOptionStrAddr(code, addr);
+ }
+
+ public String getOptionStrAddr(byte code) {
+ return dhcpOptions.getOptionStrAddr(code);
+ }
+
+ public void setOptionStrAddrs(byte code, List<String> opt) throws UnknownHostException {
+ dhcpOptions.setOptionStrAddrs(code, opt);
+ }
+
+ public void setOptionString(byte code, String str) {
+ dhcpOptions.setOptionString(code, str);
+ }
+ public boolean containsOption(byte code) {
+ // TODO Auto-generated method stub
+ return dhcpOptions.containsOption(code);
+ }
+
+ public void unsetOption(byte code) {
+ dhcpOptions.unsetOption(code);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder ret = new StringBuilder();
+ ret.append(super.toString())
+ .append(dhcpOptions);
+
+ return ret.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.vpnservice.dhcpservice.api;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.LinkedHashMap;
+
+
+
+import java.util.List;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.opendaylight.controller.liblldp.HexEncode;
+import org.opendaylight.controller.liblldp.NetUtils;
+//import org.apache.commons.lang3.ArrayUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants.*;
+
+public class DHCPOptions {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(DHCPOptions.class);
+
+ class DhcpOption extends Object {
+ private byte code;
+ private byte length;
+ private byte[] value;
+
+ public DhcpOption(byte code, byte[] value) {
+ if ((code != OPT_PAD) && (code != OPT_END) && (value != null)) {
+ this.code = code;
+ this.value = value;
+ this.length = (byte) value.length;
+ }
+ }
+
+ public byte getCode() {
+ return this.code;
+ }
+
+ public byte[] getValue() {
+ return this.value;
+ }
+
+ public byte[] serialize() {
+ byte[] opt1 = new byte[2];
+ opt1[0] = this.code;
+ opt1[1] = this.length;
+ return ArrayUtils.addAll(opt1, this.value);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{ ")
+ .append("code: ").append(this.code)
+ .append(", len: ").append(this.length)
+ .append(", value: 0x").append(HexEncode.bytesToHexString(this.value))
+ .append(" }");
+ return sb.toString();
+ }
+ }
+
+ private LinkedHashMap<Byte, DhcpOption> options;
+
+ public DHCPOptions() {
+ options = new LinkedHashMap<Byte, DhcpOption>();
+ }
+
+ private void setOption(DhcpOption opt) {
+ this.options.put(opt.getCode(), opt);
+ }
+
+ private DhcpOption getOption(byte code) {
+ return this.options.get(code);
+ }
+
+ public void setOption(byte code, byte[] opt) {
+ this.setOption(new DhcpOption(code, opt));
+ }
+
+ public byte[] getOptionBytes(byte code) {
+ try{
+ return this.getOption(code).getValue();
+ }
+ catch (NullPointerException e)
+ {
+ return null;
+ }
+ }
+
+ public void setOptionByte(byte code, byte opt) {
+ this.setOption(new DhcpOption(code, DHCPUtils.byteToByteArray(opt)));
+ }
+
+ public byte getOptionByte(byte code) {
+ return this.getOption(code).getValue()[0];
+ }
+
+ public void setOptionShort(byte code, short opt) {
+ this.setOption(new DhcpOption(code, DHCPUtils.shortToByteArray(opt)));
+ }
+
+ public short getOptionShort(byte code) {
+ byte[] opt = this.getOptionBytes(code);
+ return DHCPUtils.byteArrayToShort(opt);
+ }
+
+ public void setOptionInt(byte code, int opt) {
+ this.setOption(new DhcpOption(code, DHCPUtils.intToByteArray(opt)));
+ }
+
+ public int getOptionInt(byte code) {
+ byte[] opt = this.getOptionBytes(code);
+ return NetUtils.byteArray4ToInt(opt);
+ }
+
+ public void setOptionInetAddr(byte code, InetAddress opt) {
+ this.setOption(new DhcpOption(code, DHCPUtils.inetAddrToByteArray(opt)));
+ }
+
+ public InetAddress getOptionInetAddr(byte code) {
+ byte[] opt = this.getOptionBytes(code);
+ try {
+ return InetAddress.getByAddress(opt);
+ } catch (UnknownHostException | NullPointerException e) {
+ return null;
+ }
+ }
+
+ public void setOptionStrAddr(byte code, String opt) throws UnknownHostException {
+ this.setOption(new DhcpOption(code, DHCPUtils.strAddrToByteArray(opt)));
+ }
+
+ public String getOptionStrAddr(byte code) {
+ byte[] opt = this.getOptionBytes(code);
+ try {
+ return InetAddress.getByAddress(opt).getHostAddress();
+ } catch (UnknownHostException| NullPointerException e) {
+ return null;
+ }
+ }
+
+ public void setOptionStrAddrs(byte code, List<String> addrs) throws UnknownHostException {
+ if(!addrs.isEmpty()) {
+ this.setOption(new DhcpOption(code, DHCPUtils.strListAddrsToByteArray(addrs)));
+ }
+ }
+
+ public void setOptionString(byte code, String str) {
+ this.setOption(new DhcpOption(code, str.getBytes()));
+ }
+
+ public byte[] serialize() {
+ byte[] options = new byte[0];
+ for(DhcpOption dOpt: this.options.values()) {
+ options = ArrayUtils.addAll(options, dOpt.serialize());
+ }
+ byte[] end = new byte[] {(byte)255};
+ options = ArrayUtils.addAll(options, end);
+ return options;
+ }
+
+ private byte[] getOptionValArray(byte[] opt, int pos, int len) {
+ byte[] val = new byte[len];
+ for(int i = 0; i < len; i++) {
+ val[i] = opt[pos + i];
+ }
+ return val;
+ }
+
+ public void deserialize(byte[] options) {
+ int pos = 0;
+ byte code, len;
+ byte[] value;
+ if (options != null) {
+ while (pos < options.length) {
+ code = options[pos++];
+ if (code == OPT_END) {
+ break;
+ }
+ len = options[pos++];
+ if ((len + pos) > options.length) {
+ // Throw exception???
+ break;
+ }
+ value = getOptionValArray(options, pos, len);
+ setOption(code, value);
+ pos += len;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ int i = 1;
+ for(DhcpOption dOpt: this.options.values()) {
+ //options = ArrayUtils.addAll(options, dOpt.serialize());
+ sb.append("Option").append(i++)
+ .append(dOpt.toString());
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ public boolean containsOption(byte code) {
+ return options.containsKey(code);
+ }
+
+ public DhcpOption unsetOption(byte code) {
+ return options.remove(code);
+ }
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.vpnservice.dhcpservice;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.HostRoutes;
+
+public class DhcpInfo {
+ private String _clientIp;
+ private String _serverIp;
+ private String _gatewayIp;
+ private String _cidr;
+ private List<String> _dnsServers;
+ private List<HostRoutes> _hostRoutes;
+
+ public DhcpInfo() {
+ //Empty constructor
+ }
+
+ protected DhcpInfo setClientIp(String clientIp) {
+ _clientIp = clientIp;
+ return this;
+ }
+
+ protected DhcpInfo setCidr(String cidr) {
+ _cidr = cidr;
+ return this;
+ }
+
+ protected DhcpInfo setServerIp(String serverIp) {
+ _serverIp = serverIp;
+ return this;
+ }
+
+ protected DhcpInfo setGatewayIp(String gwIp) {
+ _gatewayIp = gwIp;
+ return this;
+ }
+
+ protected DhcpInfo setHostRoutes(List<HostRoutes> hostRoutes) {
+ _hostRoutes = hostRoutes;
+ return this;
+ }
+
+ protected DhcpInfo setDnsServers(List<String> dnsServers) {
+ _dnsServers = dnsServers;
+ return this;
+ }
+
+ protected DhcpInfo setDnsServersIpAddrs(List<IpAddress> dnsServers) {
+ for (IpAddress ipAddr: dnsServers) {
+ addDnsServer(ipAddr.getIpv4Address().getValue());
+ }
+ return this;
+ }
+
+ protected DhcpInfo addDnsServer(String dnsServerIp) {
+ if(_dnsServers == null) {
+ _dnsServers = new ArrayList<String>();
+ }
+ _dnsServers.add(dnsServerIp);
+ return this;
+ }
+
+
+ protected String getClientIp() {
+ return _clientIp;
+ }
+
+ protected String getCidr() {
+ return _cidr;
+ }
+
+ protected String getServerIp() {
+ return _serverIp ;
+ }
+
+ protected String getGatewayIp() {
+ return _gatewayIp ;
+ }
+
+ protected List<String> getDnsServers() {
+ return _dnsServers;
+ }
+
+ protected List<HostRoutes> getHostRoutes() {
+ return _hostRoutes;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.vpnservice.dhcpservice;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import com.google.common.util.concurrent.FutureCallback;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DhcpManager implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpManager.class);
+ private final DataBroker broker;
+ IMdsalApiManager mdsalUtil;
+
+ private int dhcpOptLeaseTime = 0;
+ private int dhcpOptRenewalTime = 0;
+ private int dhcpOptRebindingTime = 0;
+ private String dhcpOptDefDomainName = "openstacklocal";
+
+ private static final FutureCallback<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ logger.debug("Success in Datastore write operation");
+ }
+ public void onFailure(Throwable error) {
+ logger.error("Error in Datastore write operation", error);
+ };
+ };
+
+ /**
+ * @param db - dataBroker reference
+ */
+ public DhcpManager(final DataBroker db) {
+ broker = db;
+ configureLeaseDuration(DHCPMConstants.DEFAULT_LEASE_TIME);
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalUtil = mdsalManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ logger.info("DHCP Manager Closed");
+ }
+
+ public void installDhcpEntries(BigInteger dpnId) {
+ logger.debug("Installing Default DHCP Flow tp DPN: {}", dpnId);
+ setupDefaultDhcpFlow(dpnId, DHCPMConstants.DHCP_TABLE, NwConstants.ADD_FLOW);
+ }
+
+ private void setupDefaultDhcpFlow(BigInteger dpId, short tableId, int addOrRemove) {
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { NwConstants.ETHTYPE_IPV4 }));
+ matches.add(new MatchInfo(MatchFieldType.ip_proto,
+ new long[] { IPProtocols.UDP.intValue() }));
+ matches.add(new MatchInfo(MatchFieldType.udp_src,
+ new long[] { DHCPMConstants.dhcpClientPort }));
+ matches.add(new MatchInfo(MatchFieldType.udp_dst,
+ new long[] { DHCPMConstants.dhcpServerPort }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+
+ // Punt to controller
+ actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
+ new String[] {}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions,
+ actionsInfos));
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
+ getDefaultDhcpFlowRef(dpId, tableId),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
+ DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+ mdsalUtil.installFlow(flowEntity);
+ }
+
+ private String getDefaultDhcpFlowRef(BigInteger dpId, long tableId) {
+ return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX).append(dpId)
+ .append(NwConstants.FLOWID_SEPARATOR).append(tableId).toString();
+ }
+
+ public int setLeaseDuration(int leaseDuration) {
+ configureLeaseDuration(leaseDuration);
+ return getDhcpLeaseTime();
+ }
+
+ public String setDefaultDomain(String defaultDomain) {
+ this.dhcpOptDefDomainName = defaultDomain;
+ return getDhcpDefDomain();
+ }
+
+ protected int getDhcpLeaseTime() {
+ return this.dhcpOptLeaseTime;
+ }
+
+ protected int getDhcpRenewalTime() {
+ return this.dhcpOptLeaseTime;
+ }
+
+ protected int getDhcpRebindingTime() {
+ return this.dhcpOptLeaseTime;
+ }
+
+ protected String getDhcpDefDomain() {
+ return this.dhcpOptDefDomainName;
+ }
+
+ private void configureLeaseDuration(int leaseTime) {
+ this.dhcpOptLeaseTime = leaseTime;
+ if(leaseTime > 0) {
+ this.dhcpOptRenewalTime = this.dhcpOptLeaseTime/2;
+ this.dhcpOptRebindingTime = (this.dhcpOptLeaseTime*7)/8;
+ } else {
+ this.dhcpOptRenewalTime = -1;
+ this.dhcpOptRebindingTime = -1;
+ }
+ }
+
+ public Subnet getNeutronSubnet(Port nPort) {
+ /* TODO: Once NeutronVpn is merged, use it to get Subnet
+ if (nPort != null) {
+ try {
+ return neutronVpnService.getNeutronSubnet(nPort.getFixedIps().get(0).getSubnetId());
+ } catch (Exception e) {
+ logger.warn("Failed to get Neutron Subnet from Port: {}", e);
+ }
+ }
+ */
+ if (nPort.getFixedIps() != null && !nPort.getFixedIps().isEmpty()) {
+ InstanceIdentifier<Subnet> sIid =
+ InstanceIdentifier.create(Neutron.class).child(Subnets.class)
+ .child(Subnet.class, new SubnetKey(nPort.getFixedIps().get(0).getSubnetId()));
+ Optional<Subnet> optSubnet = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, sIid, broker);
+ if (optSubnet.isPresent()) {
+ return optSubnet.get();
+ }
+ }
+ return null;
+ }
+
+ public Port getNeutronPort(String name) {
+ // TODO Once NeutronVpn is merged, use it to get port
+ //return neutronVpnService.getNeutronPort(name);
+ InstanceIdentifier<Ports> pIid = InstanceIdentifier.create(Neutron.class).child(Ports.class);
+ Optional<Ports> optPorts = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, pIid, broker);
+ if(optPorts.isPresent()) {
+ for(Port port: optPorts.get().getPort()) {
+ if(port.getUuid().getValue().startsWith(name.substring(3))) {
+ return port;
+ }
+ }
+ }
+ return null;
+ }
+
+}
*/
package org.opendaylight.vpnservice.dhcpservice;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
+import org.opendaylight.controller.liblldp.EtherTypes;
+import org.opendaylight.controller.liblldp.HexEncode;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.PacketException;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCP;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPv4;
+import org.opendaylight.vpnservice.mdsalutil.packet.UDP;
+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.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.HostRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
private static final Logger LOG = LoggerFactory.getLogger(DhcpPktHandler.class);
private final DataBroker dataBroker;
+ private final DhcpManager dhcpMgr;
+
+ private boolean computeUdpChecksum = true;
+ private PacketProcessingService pktService;
- public DhcpPktHandler(final DataBroker broker) {
+ public DhcpPktHandler(final DataBroker broker, final DhcpManager dhcpManager) {
this.dataBroker = broker;
+ dhcpMgr = dhcpManager;
}
+ //TODO: Handle this in a separate thread
@Override
- public void onPacketReceived(PacketReceived pktReceived) {
- LOG.info("Pkt received: {}",pktReceived);
+ public void onPacketReceived(PacketReceived packet) {
+ LOG.trace("Pkt received: {}", packet);
+ Class<? extends PacketInReason> pktInReason = packet.getPacketInReason();
+ short tableId = packet.getTableId().getValue();
+ if (isPktInReasonSendtoCtrl(pktInReason) && ((DHCPMConstants.DHCP_TABLE == tableId))) {
+ byte[] inPayload = packet.getPayload();
+ Ethernet ethPkt = new Ethernet();
+ try {
+ ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
+ } catch (Exception e) {
+ LOG.warn("Failed to decode DHCP Packet", e);
+ return;
+ }
+ try {
+ DHCP pktIn = getDhcpPktIn(ethPkt);
+ LOG.trace("DHCPPkt received: {}", pktIn);
+ if (pktIn != null) {
+ NodeConnectorRef inNcRef = packet.getIngress();
+ FlowCapableNodeConnector fcNc = this.getFlowCapableNodeConnector(inNcRef);
+ DHCP replyPkt = handleDhcpPacket(pktIn, fcNc);
+ byte[] pktOut = getDhcpPacketOut(replyPkt, ethPkt, fcNc);
+ sendPacketOut(pktOut, inNcRef);
+ }
+ } catch (Exception e) {
+ LOG.warn("Failed to get DHCP Reply", e);
+ }
+ }
+ }
+
+ private void sendPacketOut(byte[] pktOut, NodeConnectorRef ingress) {
+ // We go out the same port we came in on
+ InstanceIdentifier<Node> egressNodePath = getNodePath(ingress.getValue());
+ TransmitPacketInput input = new TransmitPacketInputBuilder()
+ .setPayload(pktOut).setNode(new NodeRef(egressNodePath))
+ .setEgress(ingress).build();
+ LOG.trace("Transmitting packet: {}",input);
+ this.pktService.transmitPacket(input);
+ }
+
+ private InstanceIdentifier<Node> getNodePath(InstanceIdentifier<?> nodeInstanceId) {
+ return nodeInstanceId.firstIdentifierOf(Node.class);
+ }
+
+ private DHCP handleDhcpPacket(DHCP dhcpPkt, FlowCapableNodeConnector fcNc) {
+ LOG.debug("DHCP pkt rcvd {}", dhcpPkt);
+ byte msgType = dhcpPkt.getMsgType();
+ if (msgType == DHCPConstants.MSG_DECLINE) {
+ LOG.debug("DHCPDECLINE received");
+ return null;
+ } else if (msgType == DHCPConstants.MSG_RELEASE) {
+ LOG.debug("DHCPRELEASE received");
+ return null;
+ }
+
+ Port nPort = getNeutronPort(fcNc);
+ Subnet nSubnet = getNeutronSubnet(nPort);
+ DhcpInfo dhcpInfo = getDhcpInfo(nPort, nSubnet);
+ LOG.trace("NeutronPort: {} \n NeutronSubnet: {}, dhcpInfo{}",nPort, nSubnet, dhcpInfo);
+ DHCP reply = null;
+ if (dhcpInfo != null) {
+ if (msgType == DHCPConstants.MSG_DISCOVER) {
+ reply = getReplyToDiscover(dhcpPkt, dhcpInfo);
+ } else if (msgType == DHCPConstants.MSG_REQUEST) {
+ reply = getReplyToRequest(dhcpPkt, dhcpInfo);
+ }
+ }
+
+ return reply;
+ }
+
+ private DhcpInfo getDhcpInfo(Port nPort, Subnet nSubnet) {
+ DhcpInfo dhcpInfo = null;
+ if( (nPort != null) && (nSubnet != null) ) {
+ String clientIp = nPort.getFixedIps().get(0).getIpAddress().getIpv4Address().getValue();
+ String serverIp = nSubnet.getGatewayIp().getIpv4Address().getValue();
+ List<IpAddress> dnsServers = nSubnet.getDnsNameservers();
+ dhcpInfo = new DhcpInfo();
+ dhcpInfo.setClientIp(clientIp).setServerIp(serverIp)
+ .setCidr(nSubnet.getCidr()).setHostRoutes(nSubnet.getHostRoutes())
+ .setDnsServersIpAddrs(dnsServers).setGatewayIp(serverIp);
+ } else {
+ //FIXME: Delete this test code
+ LOG.error("TestOnly Code");
+ dhcpInfo = new DhcpInfo();
+ dhcpInfo.setClientIp("1.1.1.3").setServerIp("1.1.1.1")
+ .setCidr("1.1.1.0/24").addDnsServer("1.1.1.1");
+ LOG.warn("Failed to get Subnet info for DHCP reply");
+ }
+ return dhcpInfo;
+ }
+
+ private Subnet getNeutronSubnet(Port nPort) {
+ return dhcpMgr.getNeutronSubnet(nPort);
+ }
+
+ private Port getNeutronPort(FlowCapableNodeConnector fcNc) {
+ return dhcpMgr.getNeutronPort(fcNc.getName());
+ }
+
+ private FlowCapableNodeConnector getFlowCapableNodeConnector(NodeConnectorRef inNcRef) {
+ InstanceIdentifier<NodeConnector> ncId = inNcRef.getValue().firstIdentifierOf(NodeConnector.class);
+ Optional<NodeConnector> nodeConnector =
+ MDSALDataStoreUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ncId);
+ if(nodeConnector.isPresent()) {
+ NodeConnector nc = nodeConnector.get();
+ LOG.trace("Incoming pkt's NodeConnector: {}", nc);
+ FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class);
+ return fcnc;
+ }
+ return null;
+ }
+
+ private DHCP getDhcpPktIn(Ethernet ethPkt) {
+ if (ethPkt.getPayload() instanceof IPv4) {
+ IPv4 ipPkt = (IPv4) ethPkt.getPayload();
+ if (ipPkt.getPayload() instanceof UDP) {
+ UDP udpPkt = (UDP) ipPkt.getPayload();
+ if ((udpPkt.getSourcePort() == DHCPMConstants.dhcpClientPort)
+ && (udpPkt.getDestinationPort() == DHCPMConstants.dhcpServerPort)) {
+ byte[] rawDhcpPayload = udpPkt.getRawPayload();
+ DHCP reply = new DHCP();
+ try {
+ reply.deserialize(rawDhcpPayload, 0, rawDhcpPayload.length);
+ } catch (PacketException e) {
+ LOG.warn("Failed to deserialize DHCP pkt", e);
+ return null;
+ }
+ return reply;
+ }
+ }
+ }
+ return null;
+ }
+
+ DHCP getReplyToDiscover(DHCP dhcpPkt, DhcpInfo dhcpInfo) {
+ DHCP reply = new DHCP();
+ reply.setOp(DHCPConstants.BOOTREPLY);
+ reply.setHtype(dhcpPkt.getHtype());
+ reply.setHlen(dhcpPkt.getHlen());
+ reply.setHops((byte) 0);
+ reply.setXid(dhcpPkt.getXid());
+ reply.setSecs((short) 0);
+
+ reply.setYiaddr(dhcpInfo.getClientIp());
+ reply.setSiaddr(dhcpInfo.getServerIp());
+
+ reply.setFlags(dhcpPkt.getFlags());
+ reply.setGiaddr(dhcpPkt.getGiaddr());
+ reply.setChaddr(dhcpPkt.getChaddr());
+
+ reply.setMsgType(DHCPConstants.MSG_OFFER);
+ if(dhcpPkt.containsOption(DHCPConstants.OPT_PARAMETER_REQUEST_LIST)) {
+ setParameterListOptions(dhcpPkt, reply, dhcpInfo);
+ }
+ setCommonOptions(reply, dhcpInfo);
+ return reply;
+ }
+
+ DHCP getReplyToRequest(DHCP dhcpPkt, DhcpInfo dhcpInfo) {
+ boolean sendAck = false;
+ byte[] requestedIp = null;
+ DHCP reply = new DHCP();
+ reply.setOp(DHCPConstants.BOOTREPLY);
+ reply.setHtype(dhcpPkt.getHtype());
+ reply.setHlen(dhcpPkt.getHlen());
+ reply.setHops((byte) 0);
+ reply.setXid(dhcpPkt.getXid());
+ reply.setSecs((short) 0);
+
+ reply.setFlags(dhcpPkt.getFlags());
+ reply.setGiaddr(dhcpPkt.getGiaddr());
+ reply.setChaddr(dhcpPkt.getChaddr());
+ byte[] allocatedIp = DHCPUtils.strAddrToByteArray(dhcpInfo.getClientIp());
+ if(Arrays.equals(allocatedIp, dhcpPkt.getCiaddr())) {
+ //This means a renew request
+ sendAck = true;
+ } else {
+ requestedIp = dhcpPkt.getOptionBytes(DHCPConstants.OPT_REQUESTED_ADDRESS);
+ sendAck = Arrays.equals(allocatedIp, requestedIp);
+ }
+
+ if (sendAck) {
+ reply.setCiaddr(dhcpPkt.getCiaddr());
+ reply.setYiaddr(dhcpInfo.getClientIp());
+ reply.setSiaddr(dhcpInfo.getServerIp());
+ reply.setMsgType(DHCPConstants.MSG_ACK);
+ if(dhcpPkt.containsOption(DHCPConstants.OPT_PARAMETER_REQUEST_LIST)) {
+ setParameterListOptions(dhcpPkt, reply, dhcpInfo);
+ }
+ setCommonOptions(reply, dhcpInfo);
+ }
+ else {
+ reply.setMsgType(DHCPConstants.MSG_NAK);
+ }
+ return reply;
+ }
+
+ protected byte[] getDhcpPacketOut(DHCP reply, Ethernet etherPkt, FlowCapableNodeConnector fcNc) {
+ if (reply == null) {
+ /*
+ * DECLINE or RELEASE don't result in reply packet
+ */
+ return null;
+ }
+ LOG.debug("Sending DHCP Pkt {}", reply);
+ // create UDP pkt
+ UDP udpPkt = new UDP();
+ byte[] rawPkt;
+ try {
+ rawPkt = reply.serialize();
+ } catch (PacketException e2) {
+ // TODO Auto-generated catch block
+ e2.printStackTrace();
+ return null;
+ }
+ udpPkt.setRawPayload(rawPkt);
+ udpPkt.setDestinationPort(DHCPMConstants.dhcpClientPort);
+ udpPkt.setSourcePort(DHCPMConstants.dhcpServerPort);
+ udpPkt.setLength((short) (rawPkt.length + 8));
+ //Create IP Pkt
+ IPv4 ip4Reply = new IPv4();
+ try {
+ rawPkt = udpPkt.serialize();
+ } catch (PacketException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ short checkSum = 0;
+ if(this.computeUdpChecksum) {
+ checkSum = computeChecksum(rawPkt, reply.getSiaddr(),
+ NetUtils.intToByteArray4(DHCPMConstants.BCAST_IP));
+ }
+ udpPkt.setChecksum(checkSum);
+ ip4Reply.setPayload(udpPkt);
+ ip4Reply.setProtocol(IPProtocols.UDP.byteValue());
+ ip4Reply.setSourceAddress(reply.getSiaddrAsInetAddr());
+ ip4Reply.setDestinationAddress(DHCPMConstants.BCAST_IP);
+ ip4Reply.setTotalLength((short) (rawPkt.length+20));
+ ip4Reply.setTtl((byte) 32);
+ // create Ethernet Frame
+ Ethernet ether = new Ethernet();
+ //TODO:
+ ether.setSourceMACAddress(getServerMacAddress(fcNc));
+ ether.setDestinationMACAddress(etherPkt.getSourceMACAddress());
+ ether.setEtherType(EtherTypes.IPv4.shortValue());
+ ether.setPayload(ip4Reply);
+ try {
+ rawPkt = ether.serialize();
+ } catch (PacketException e) {
+ LOG.warn("Failed to serialize ethernet reply",e);
+ return null;
+ }
+ return rawPkt;
+ }
+
+ private byte[] getServerMacAddress(FlowCapableNodeConnector fcNc) {
+ // Should we return ControllerMac instead?
+ MacAddress macAddress = fcNc.getHardwareAddress();
+ return DHCPUtils.strMacAddrtoByteArray(macAddress.getValue());
+ }
+
+ public short computeChecksum(byte[] inData, byte[] srcAddr, byte[] destAddr) {
+ short checkSum = (short) 0;
+ int sum = 0, carry = 0;
+ int wordData, i;
+
+ for (i = 0; i < inData.length - 1; i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ wordData = ((inData[i] << 8) & 0xFF00) + (inData[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+
+ if (i < inData.length) {
+ wordData = ((inData[i] << 8) & 0xFF00) + (0 & 0xFF);
+ sum = sum + wordData;
+ }
+
+ for (i = 0; i < 4; i = i + 2) {
+ wordData = ((srcAddr[i] << 8) & 0xFF00) + (srcAddr[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+
+ for (i = 0; i < 4; i = i + 2) {
+ wordData = ((destAddr[i] << 8) & 0xFF00) + (destAddr[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+ sum = sum + 17 + inData.length;
+
+ while((sum >> 16) != 0) {
+ carry = (sum >> 16);
+ sum = (sum & 0xFFFF)+ carry;
+ }
+ checkSum = (short) ~((short) sum & 0xFFFF);
+ if(checkSum == 0) {
+ checkSum = (short)0xffff;
+ }
+ return checkSum;
+ }
+
+ private void setCommonOptions(DHCP pkt, DhcpInfo dhcpInfo) {
+ pkt.setOptionInt(DHCPConstants.OPT_LEASE_TIME, dhcpMgr.getDhcpLeaseTime());
+ if (dhcpMgr.getDhcpDefDomain() != null) {
+ pkt.setOptionString(DHCPConstants.OPT_DOMAIN_NAME, dhcpMgr.getDhcpDefDomain());
+ }
+ if(dhcpMgr.getDhcpLeaseTime() > 0) {
+ pkt.setOptionInt(DHCPConstants.OPT_REBINDING_TIME, dhcpMgr.getDhcpRebindingTime());
+ pkt.setOptionInt(DHCPConstants.OPT_RENEWAL_TIME, dhcpMgr.getDhcpRenewalTime());
+ }
+ SubnetUtils util = null;
+ SubnetInfo info = null;
+ util = new SubnetUtils(dhcpInfo.getCidr());
+ info = util.getInfo();
+ String gwIp = dhcpInfo.getGatewayIp();
+ List<String> dnServers = dhcpInfo.getDnsServers();
+ try {
+ /*
+ * setParameterListOptions may have initialized some of these
+ * options to maintain order. If we can't fill them, unset to avoid
+ * sending wrong information in reply.
+ */
+ if (gwIp != null) {
+ pkt.setOptionInetAddr(DHCPConstants.OPT_SERVER_IDENTIFIER, gwIp);
+ pkt.setOptionInetAddr(DHCPConstants.OPT_ROUTERS, gwIp);
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_SERVER_IDENTIFIER);
+ pkt.unsetOption(DHCPConstants.OPT_ROUTERS);
+ }
+ if (info != null) {
+ pkt.setOptionInetAddr(DHCPConstants.OPT_SUBNET_MASK, info.getNetmask());
+ pkt.setOptionInetAddr(DHCPConstants.OPT_BROADCAST_ADDRESS, info.getBroadcastAddress());
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_SUBNET_MASK);
+ pkt.unsetOption(DHCPConstants.OPT_BROADCAST_ADDRESS);
+ }
+ if ((dnServers != null) && (dnServers.size() > 0)) {
+ pkt.setOptionStrAddrs(DHCPConstants.OPT_DOMAIN_NAME_SERVERS, dnServers);
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_DOMAIN_NAME_SERVERS);
+ }
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void setParameterListOptions(DHCP req, DHCP reply, DhcpInfo dhcpInfo) {
+ byte[] paramList = req.getOptionBytes(DHCPConstants.OPT_PARAMETER_REQUEST_LIST);
+ for(int i = 0; i < paramList.length; i++) {
+ switch (paramList[i]) {
+ case DHCPConstants.OPT_SUBNET_MASK:
+ case DHCPConstants.OPT_ROUTERS:
+ case DHCPConstants.OPT_SERVER_IDENTIFIER:
+ case DHCPConstants.OPT_DOMAIN_NAME_SERVERS:
+ case DHCPConstants.OPT_BROADCAST_ADDRESS:
+ case DHCPConstants.OPT_LEASE_TIME:
+ case DHCPConstants.OPT_RENEWAL_TIME:
+ case DHCPConstants.OPT_REBINDING_TIME:
+ /* These values will be filled in setCommonOptions
+ * Setting these just to preserve order as
+ * specified in PARAMETER_REQUEST_LIST.
+ */
+ reply.setOptionInt(paramList[i], 0);
+ break;
+ case DHCPConstants.OPT_DOMAIN_NAME:
+ reply.setOptionString(paramList[i], " ");
+ break;
+ case DHCPConstants.OPT_CLASSLESS_ROUTE:
+ setOptionClasslessRoute(reply, dhcpInfo);
+ break;
+ default:
+ LOG.debug("DHCP Option code {} not supported yet", paramList[i]);
+ break;
+ }
+ }
+ }
+ private void setOptionClasslessRoute(DHCP reply, DhcpInfo dhcpInfo) {
+ List<HostRoutes> hostRoutes = dhcpInfo.getHostRoutes();
+ if(hostRoutes == null) {
+ //we can't set this option, so return
+ return;
+ }
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ Iterator<HostRoutes> iter = hostRoutes.iterator();
+ while(iter.hasNext()) {
+ HostRoutes hostRoute = iter.next();
+ String router = hostRoute.getNexthop().toString();
+ String dest = hostRoute.getDestination().toString();
+ try {
+ result.write(convertToClasslessRouteOption(dest, router));
+ } catch (IOException | NullPointerException e) {
+ LOG.debug("Exception {}",e.getMessage());
+ }
+ }
+ if (result.size() > 0) {
+ reply.setOptionBytes(DHCPConstants.OPT_CLASSLESS_ROUTE , result.toByteArray());
+ }
+ }
+
+ protected byte[] convertToClasslessRouteOption(String dest, String router) {
+ ByteArrayOutputStream bArr = new ByteArrayOutputStream();
+ if((dest == null ||
+ router == null)) {
+ return null;
+ }
+
+ //get prefix
+ Short prefix = null;
+ String[] parts = dest.split("/");
+ if (parts.length < 2) {
+ prefix = new Short((short)0);
+ } else {
+ prefix = Short.valueOf(parts[1]);
+ }
+
+ bArr.write(prefix.byteValue());
+ SubnetUtils util = new SubnetUtils(dest);
+ SubnetInfo info = util.getInfo();
+ String strNetAddr = info.getNetworkAddress();
+ try {
+ byte[] netAddr = InetAddress.getByName(strNetAddr).getAddress();
+ //Strip any trailing 0s from netAddr
+ for(int i = 0; i < netAddr.length;i++) {
+ if(netAddr[i] != 0) {
+ bArr.write(netAddr,i,1);
+ }
+ }
+ bArr.write(InetAddress.getByName(router).getAddress());
+ } catch (IOException e) {
+ return null;
+ }
+ return bArr.toByteArray();
+ }
+
+ private boolean isPktInReasonSendtoCtrl(Class<? extends PacketInReason> pktInReason) {
+ return (pktInReason == SendToController.class);
}
@Override
public void close() throws Exception {
// TODO Auto-generated method stub
-
+ }
+
+ public void setPacketProcessingService(PacketProcessingService packetService) {
+ this.pktService = packetService;
}
}
*/
package org.opendaylight.vpnservice.dhcpservice;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import java.math.BigInteger;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
private DhcpPktHandler dhcpPktHandler;
private Registration packetListener = null;
private NotificationProviderService notificationService;
+ private DhcpManager dhcpManager;
+ private NodeListener dhcpNodeListener;
@Override
public void onSessionInitiated(ProviderContext session) {
LOG.info("DhcpProvider Session Initiated");
try {
- final DataBroker dataBroker = session.getSALService(DataBroker.class);
- dhcpPktHandler = new DhcpPktHandler(dataBroker);
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ final PacketProcessingService pktProcessingService = session.getRpcService(PacketProcessingService.class);
+ dhcpManager = new DhcpManager(dataBroker);
+ dhcpManager.setMdsalManager(mdsalManager);
+ dhcpPktHandler = new DhcpPktHandler(dataBroker, dhcpManager);
+ dhcpPktHandler.setPacketProcessingService(pktProcessingService);
packetListener = notificationService.registerNotificationListener(dhcpPktHandler);
- } catch (Exception e) {
+ dhcpNodeListener = new NodeListener(dataBroker, dhcpManager);
+ } catch (Exception e) {
LOG.error("Error initializing services", e);
}
}
if(dhcpPktHandler != null) {
dhcpPktHandler.close();
}
+ if(dhcpNodeListener != null) {
+ dhcpNodeListener.close();
+ }
LOG.info("DhcpProvider closed");
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.vpnservice.dhcpservice;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+public class NodeListener extends AbstractDataChangeListener<Node> implements AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NodeListener.class);
+
+ private IMdsalApiManager mdsalManager;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private DhcpManager dhcpManager;
+
+ public NodeListener(final DataBroker db, final DhcpManager dhcpMgr) {
+ super(Node.class);
+ broker = db;
+ dhcpManager = dhcpMgr;
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), NodeListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("NodeListener: DataChange listener registration fail!", e);
+ throw new IllegalStateException("NodeListener: registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Node> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class);
+ }
+
+
+ @Override
+ protected void remove(InstanceIdentifier<Node> identifier, Node del) {
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Node> identifier, Node original, Node update) {
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Node> identifier, Node add) {
+ NodeId nodeId = add.getId();
+ String[] node = nodeId.getValue().split(":");
+ BigInteger dpId = new BigInteger(node[1]);
+ dhcpManager.installDhcpEntries(dpId);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up NodeListener.", e);
+ }
+ listenerRegistration = null;
+ //ToDo: Should we delete DHCP flows when we are closed?
+ }
+ LOG.debug("Node Listener Closed");
+ }
+}
public java.lang.AutoCloseable createInstance() {
DhcpProvider dhcpProvider = new DhcpProvider();
dhcpProvider.setNotificationProviderService(getNotificationServiceDependency());
+ dhcpProvider.setMdsalManager(getMdsalutilDependency());
getBrokerDependency().registerProvider(dhcpProvider);
return dhcpProvider;
}
<vpnservices.version>0.2.0-SNAPSHOT</vpnservices.version>
<ovsdb.version>1.2.1-SNAPSHOT</ovsdb.version>
<liblldp.version>0.10.0-SNAPSHOT</liblldp.version>
+ <neutron.version>0.6.0-SNAPSHOT</neutron.version>
<arputil.version>${vpnservices.version}</arputil.version>
<mdsalutil.version>${vpnservices.version}</mdsalutil.version>
<vpnmanager.version>${vpnservices.version}</vpnmanager.version>
<type>xml</type>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>features-neutron</artifactId>
+ <classifier>features</classifier>
+ <version>${neutron.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>dummyprovider</artifactId>
+ <version>${neutron.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>vpnmanager-impl</artifactId>
<artifactId>libthrift</artifactId>
<version>0.9.1</version>
</dependency>
+ <dependency>
+ <groupId>commons-net</groupId>
+ <artifactId>commons-net</artifactId>
+ <version>${commons.net.version}</version>
+ </dependency>
</dependencies>
</project>
<repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features</repository>
<repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
<repository>mvn:org.opendaylight.ovsdb/features-ovsdb/${ovsdb.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.neutron/features-neutron/${neutron.version}/xml/features</repository>
<feature name='odl-vpnservice-api' version='${project.version}' description='OpenDaylight :: vpnservice :: api '>
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
<feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
<feature version='${openflowplugin.version}'>odl-openflowplugin-nsf-model</feature>
<bundle>mvn:org.opendaylight.controller/liblldp/${liblldp.version}</bundle>
+ <bundle>mvn:org.opendaylight.neutron/model/${neutron.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/model-bgp/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/lockmanager-api/${lockmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/idmanager-api/${idmanager.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/mdsalutil-api/${vpnservices.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/arputil-api/${arputil.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/alivenessmonitor-api/${vpnservices.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/vpnmanager-api/${vpnmanager.version}</bundle>
<feature version='${project.version}'>odl-vpnservice-api</feature>
<feature version="${openflowplugin.version}">odl-openflowplugin-southbound</feature>
<feature version="${openflowplugin.version}">odl-openflowplugin-flow-services</feature>
+ <bundle>mvn:commons-net/commons-net/${commons.net.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/lockmanager-impl/${lockmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/idmanager-impl/${idmanager.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/bgpmanager-api/${vpnservices.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/bgpmanager-impl/${vpnservices.version}</bundle>
- <bundle>mvn:org.opendaylight.vpnservice/mdsalutil-api/${interfacemgr.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/mdsalutil-api/${vpnservices.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/arputil-impl/${arputil.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/alivenessmonitor-impl/${vpnservices.version}</bundle>
- <bundle>mvn:org.opendaylight.vpnservice/mdsalutil-impl/${interfacemgr.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/mdsalutil-impl/${vpnservices.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/interfacemgr-api/${interfacemgr.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/interfacemgr-impl/${interfacemgr.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/vpnmanager-impl/${vpnmanager.version}</bundle>
<configfile finalname="idmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/idmanager-impl/${idmanager.version}/xml/config</configfile>
<configfile finalname="idmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/idmanager-impl/${idmanager.version}/xml/config</configfile>
<configfile finalname="bgpmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/bgpmanager-impl/${vpnservices.version}/xml/config</configfile>
- <configfile finalname="mdsalutil-impl-default-config.xml">mvn:org.opendaylight.vpnservice/mdsalutil-impl/${interfacemgr.version}/xml/config</configfile>
+ <configfile finalname="mdsalutil-impl-default-config.xml">mvn:org.opendaylight.vpnservice/mdsalutil-impl/${vpnservices.version}/xml/config</configfile>
<configfile finalname="interfacemgr-impl-default-config.xml">mvn:org.opendaylight.vpnservice/interfacemgr-impl/${interfacemgr.version}/xml/config</configfile>
<configfile finalname="arputil-impl-default-config.xml">mvn:org.opendaylight.vpnservice/arputil-impl/${arputil.version}/xml/config</configfile>
<configfile finalname="alivenessmonitor-impl-default-config.xml">mvn:org.opendaylight.vpnservice/alivenessmonitor-impl/${vpnservices.version}/xml/config</configfile>
<feature version="${mdsal.version}">odl-mdsal-xsql</feature>
</feature>
<feature name='odl-vpnservice-core' version='${project.version}' description='OpenDaylight :: vpnservice :: core'>
+ <feature version="${neutron.version}">odl-neutron-service</feature>
+ <bundle>mvn:org.opendaylight.neutron/dummyprovider/${neutron.version}</bundle>
<feature version="${project.version}">odl-vpnservice-impl-ui</feature>
</feature>
<feature name='odl-vpnservice-openstack' version='${project.version}' description='OpenDaylight :: vpnservice :: impl :: REST '>
hdrFieldsMap = fieldValues;
}
- /**
- * Constructor that sets the access level for the packet and
- * creates and sets the HashMap
- */
public ARP(boolean writeAccess) {
super(writeAccess);
fieldValues = new HashMap<String, byte[]>();
static {
etherTypeClassMap = new HashMap<Short, Class<? extends Packet>>();
etherTypeClassMap.put(EtherTypes.ARP.shortValue(), ARP.class);
+ etherTypeClassMap.put(EtherTypes.LLDP.shortValue(), LLDP.class);
+ etherTypeClassMap.put(EtherTypes.IPv4.shortValue(), IPv4.class);
// TODO: Add support for more classes here
// etherTypeClassMap.put(EtherTypes.VLANTAGGED.shortValue(), IEEE8021Q.class);
// etherTypeClassMap.put(EtherTypes.OLDQINQ.shortValue(), IEEE8021Q.class);
/**
* Constructor that sets the access level for the packet and
* creates and sets the HashMap
+ * @param writeAccess boolean
*/
public Ethernet(boolean writeAccess) {
super(writeAccess);
--- /dev/null
+/*
+ * 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.vpnservice.mdsalutil.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.BufferException;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.liblldp.PacketException;
+
+/**
+ * Class that represents the ICMP packet objects
+ */
+
+public class ICMP extends Packet {
+ private static final String TYPE = "Type";
+ private static final String CODE = "Code";
+ private static final String CHECKSUM = "Checksum";
+ private static final String IDENTIFIER = "Identifier";
+ private static final String SEQNUMBER = "SequenceNumber";
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(TYPE, new ImmutablePair<Integer, Integer>(0, 8));
+ put(CODE, new ImmutablePair<Integer, Integer>(8, 8));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(16, 16));
+ put(IDENTIFIER, new ImmutablePair<Integer, Integer>(32, 16));
+ put(SEQNUMBER, new ImmutablePair<Integer, Integer>(48, 16));
+ }
+ };
+
+ /**
+ * Default constructor that creates and sets the hash map values
+ */
+ public ICMP() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ /**
+ * Constructor that sets the access level for the packet
+ * @param writeAccess - boolean
+ */
+ public ICMP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ private final Map<String, byte[]> fieldValues;
+
+ @Override
+ public void setHeaderField(String headerField, byte[] readValue) {
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ /**
+ * Sets the type for the current ICMP message
+ *
+ * @param type
+ * The ICMP message type
+ * @return This ICMP object
+ */
+ public ICMP setType(byte type) {
+ byte[] icmpType = BitBufferHelper.toByteArray(type);
+ fieldValues.put(TYPE, icmpType);
+ return this;
+ }
+
+ /**
+ * Returns the type field of the current ICMP packet
+ *
+ * @return The type code of the current ICMP packet
+ */
+ public byte getType() {
+ return BitBufferHelper.getByte(fieldValues.get(TYPE));
+ }
+
+ /**
+ * Sets the ICMP code (type subtype) for the current ICMP object instance
+ *
+ * @param code
+ * The ICMP message type subtype
+ * @return This ICMP object
+ */
+ public ICMP setCode(byte code) {
+ byte[] icmpCode = BitBufferHelper.toByteArray(code);
+ fieldValues.put(CODE, icmpCode);
+ return this;
+ }
+
+ /**
+ * Gets the ICMP code (type subtype) for the current ICMP object instance
+ *
+ * @return The ICMP message type subtype
+ */
+ public byte getCode() {
+ return BitBufferHelper.getByte(fieldValues.get(CODE));
+ }
+
+ /**
+ * Sets the ICMP checksum for the current ICMP object instance
+ * @param checksum - short
+ * @return ICMP
+ */
+ public ICMP setChecksum(short checksum) {
+ byte[] icmpChecksum = BitBufferHelper.toByteArray(checksum);
+ fieldValues.put(CHECKSUM, icmpChecksum);
+ return this;
+ }
+
+ /**
+ * Sets the ICMP identifier for the current ICMP object instance
+ * @param identifier - short
+ * @return ICMP
+ */
+ public ICMP setIdentifier(short identifier) {
+ byte[] icmpIdentifier = BitBufferHelper.toByteArray(identifier);
+ fieldValues.put(IDENTIFIER, icmpIdentifier);
+ return this;
+ }
+
+ /**
+ * Gets the ICMP identifier of the current ICMP object instance
+ *
+ * @return short - identifier
+ */
+
+ public short getIdentifier() {
+ return BitBufferHelper.getShort(fieldValues.get(IDENTIFIER));
+ }
+
+ /**
+ * Sets the ICMP sequence number for the current ICMP object instance
+ * @param seqNumber-short
+ * @return ICMP
+ */
+ public ICMP setSequenceNumber(short seqNumber) {
+ byte[] icmpSeqNumber = BitBufferHelper.toByteArray(seqNumber);
+ fieldValues.put(SEQNUMBER, icmpSeqNumber);
+ return this;
+ }
+
+ /**
+ * Gets the ICMP sequence number of the current ICMP object instance
+ *
+ * @return short - seqNumber
+ */
+
+ public short getSequenceNumber() {
+ return BitBufferHelper.getShort(fieldValues.get(SEQNUMBER));
+ }
+
+ /**
+ * Gets the header size in bits
+ * @return The ICMP header size in bits
+ */
+ @Override
+ public int getHeaderSize() {
+ return 64;
+ }
+
+ /**
+ * Computes the ICMP checksum on the serialized ICMP message
+ *
+ * @param data
+ * The serialized data stream
+ * @param start
+ * The byte index on the data stream from which the ICMP packet
+ * starts
+ * @return The checksum
+ */
+ short computeChecksum(byte[] data, int start) {
+ int sum = 0, carry = 0, finalSum = 0;
+ int wordData;
+ int end = start + this.getHeaderSize() / NetUtils.NumBitsInAByte;
+ if (rawPayload != null) {
+ end += rawPayload.length;
+ }
+ int checksumStartByte = start + getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte;
+ int even = end & ~1;
+
+ for (int i = start; i < even; i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ if (i == checksumStartByte) {
+ continue;
+ }
+ wordData = ((data[i] << 8) & 0xFF00) + (data[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+ if (even < end) {
+ // Add the last octet with zero padding.
+ wordData = (data[even] << 8) & 0xFF00;
+ sum = sum + wordData;
+ }
+
+ carry = sum >>> 16;
+ finalSum = (sum & 0xFFFF) + carry;
+ return (short) ~((short) finalSum & 0xFFFF);
+ }
+
+ @Override
+ protected void postSerializeCustomOperation(byte[] serializedBytes)
+ throws PacketException {
+ byte[] checkSum = BitBufferHelper
+ .toByteArray(computeChecksum(serializedBytes, 0));
+ try {
+ BitBufferHelper.setBytes(serializedBytes, checkSum,
+ getfieldOffset(CHECKSUM), getfieldnumBits(CHECKSUM));
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+ }
+
+ @Override
+ protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) {
+ short computedChecksum = computeChecksum(data, endBitOffset / NetUtils.NumBitsInAByte);
+ short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
+
+ if (computedChecksum != actualChecksum) {
+ corrupted = true;
+ }
+ }
+
+ /**
+ * Gets the checksum value stored
+ * @return the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
+ }
+}
--- /dev/null
+/*
+ * 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.vpnservice.mdsalutil.packet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enum represents the most common IP protocols numbers It provides the binding
+ * between IP protocol names and numbers and provides APIs to read and parse
+ * them in either of the two forms
+ *
+ * NOTE: Openflow 1.0 supports the IP Proto match only for ICMP, TCP and UDP
+ *
+ * references:
+ * http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
+ */
+public enum IPProtocols {
+ ANY("any", -1),
+ HOPOPT("HOPOPT",0),
+ ICMP("ICMP", 1),
+ IGMP("IGMP",2),
+ GGP("GGP",3),
+ IPV4("IPv4",4),
+ ST("ST",5),
+ TCP("TCP", 6),
+ CBT("CBT",7),
+ EGP("EGP",8),
+ IGP("IGP",9),
+ BBNRCCMON("BBN-RCC-MON",10),
+ NVPII("NVP-II",11),
+ PUP("PUP",12),
+ ARGUS("ARGUS",13),
+ EMCON("EMCON",14),
+ XNET("XNET",15),
+ CHAOS("CHAOS",16),
+ UDP("UDP", 17),
+ MUX("MUX",18),
+ DCNMEAS("DCN-MEAS",19),
+ HMP("HMP",20),
+ PRM("PRM",21),
+ XNSIDP("XNS-IDP",22),
+ TRUNK1("TRUNK-1",23),
+ TRUNK2("TRUNK-2",24),
+ LEAF1("LEAF-1",25),
+ LEAF2("LEAF-2",26),
+ RDP("RDP",27),
+ IRTP("IRTP",28),
+ ISOTP4("ISO-TP4",29),
+ NETBLT("NETBLT",30),
+ MFENSP("MFE-NSP",31),
+ MERITINP("MERIT-INP",32),
+ DCCP("DCCP",33),
+ THREEPC("3PC",34),
+ IDPR("IDPR",35),
+ XTP("XTP",36),
+ DDP("DDP",37),
+ IDPRCMTP("IDPR-CMTP",38),
+ TPPLUSPLUS("TP++",39),
+ IL("IL",40),
+ IPV6("IPv6",41),
+ SDRP("SDRP",42),
+ IPV6Route("IPv6-Route",43),
+ IPV6Frag("IPv6-Frag",44),
+ IDRP("IDRP",45),
+ RSVP("RSVP",46),
+ GRE("GRE",47),
+ DSR("DSR",48),
+ BNA("BNA",49),
+ ESP("ESP",50),
+ AH("AH",51),
+ INLSP("I-NLSP",52),
+ SWIPE("SWIPE",53),
+ NARP("NARP",54),
+ MOBILE("MOBILE",55),
+ TLSP("TLSP",56),
+ SKIP("SKIP",57),
+ IPV6ICMP("IPv6-ICMP", 58),
+ IPV6NoNxt("IPv6-NoNxt",59),
+ IPV6Opts("IPv6-Opts",60),
+ ANYHOST("ANY-HOST",61),
+ CFTP("CFTP",62),
+ ANYNETWORK("ANY-NETWORK",63),
+ SATEXPAK("SAT-EXPAK",64),
+ KRYPTOLAN("KRYPTOLAN",65),
+ RVD("RVD",66),
+ IPPC("IPPC",67),
+ ANYDISTFS("ANY-DIST-FS",68),
+ SATMON("SAT-MON",69),
+ VISA("VISA",70),
+ IPCV("IPCV",71),
+ CPNX("CPNX",72),
+ CPHB("CPHB",73),
+ WSN("WSN",74),
+ PVP("PVP",75),
+ BRSATMON("BR-SAT-MON",76),
+ SUNND("SUN-ND",77),
+ WBMON("WB-MON",78),
+ WBEXPAK("WB-EXPAK",79),
+ ISOIP("ISO-IP",80),
+ VMTP("VMTP",81),
+ SECUREVMTP("SECURE-VMTP",82),
+ VINES("VINES",83),
+ TTP("TTP",84),
+ IPTM("IPTM",84),
+ NSFNETIGP("NSFNET-IGP",85),
+ DGP("DGP",86),
+ TCF("TCF",87),
+ EIGRP("EIGRP",88),
+ OSPFIGP("OSPFIGP",89),
+ SPRITERPC("Sprite-RPC",90),
+ LARP("LARP",91),
+ MTP("MTP",92),
+ AX25("AX.25",93),
+ IPIP("IPIP",94),
+ MICP("MICP",95),
+ SCCSP("SCC-SP",96),
+ ETHERIP("ETHERIP",97),
+ ENCAP("ENCAP",98),
+ ANYENC("ANY-ENC",99),
+ GMTP("GMTP",100),
+ IFMP("IFMP",101),
+ PNNI("PNNI",102),
+ PIM("PIM",103),
+ ARIS("ARIS",104),
+ SCPS("SCPS",105),
+ QNX("QNX",106),
+ AN("A/N",107),
+ IPComp("IPComp",108),
+ SNP("SNP",109),
+ COMPAQPEER("Compaq-Peer",110),
+ IPXINIP("IPX-in-IP",111),
+ VRRP("VRRP",112),
+ PGM("PGM",113),
+ ANY0HOP("ANY-0-HOP",114),
+ L2TP("L2TP",115),
+ DDX("DDX",116),
+ IATP("IATP",117),
+ STP("STP",118),
+ SRP("SRP",119),
+ UTI("UTI",120),
+ SMP("SMP",121),
+ SM("SM",122),
+ PTP("PTP",123),
+ ISIS("ISIS",124),
+ FIRE("FIRE",125),
+ CRTP("CRTP",126),
+ CRUDP("CRUDP",127),
+ SSCOPMCE("SSCOPMCE",128),
+ IPLT("IPLT",129),
+ SPS("SPS",130),
+ PIPE("PIPE",131),
+ SCTP("SCTP",132),
+ FC("FC",133),
+ RSVPE2EIGNORE("RSVP-E2E-IGNORE",134),
+ MOBILITYHEADER("Mobility Header",135),
+ UDPLITE("UDPLite",136),
+ MPLSINIP("MPLS-in-IP",137),
+ MANET("MANET",138),
+ HIP("HIP",139),
+ SHIM6("Shim6",140),
+ WESP("WESP",141),
+ ROHC("ROHC",142),
+ /*143-252 Unassigned by IANA*/
+
+ //Experimebtal protocol numbers (http://tools.ietf.org/html/rfc3692)
+ EXP1("Experimental1", 253),
+ EXP2("Experimental2", 254),
+
+ RESERVED("RESERVED",255);
+
+ private String protocolName;
+ private int protocolNumber;
+
+ private IPProtocols(String name, int number) {
+ protocolName = name;
+ protocolNumber = number;
+ }
+
+ public int intValue() {
+ return protocolNumber;
+ }
+
+ public short shortValue() {
+ return ((Integer) protocolNumber).shortValue();
+ }
+
+ public byte byteValue() {
+ return ((Integer) protocolNumber).byteValue();
+ }
+
+ @Override
+ public String toString() {
+ return protocolName;
+ }
+
+ public static String getProtocolName(int number) {
+ return getProtocolNameInternal(number);
+ }
+
+ public static String getProtocolName(short number) {
+ return getProtocolNameInternal(number & 0xffff);
+ }
+
+ public static String getProtocolName(byte number) {
+ return getProtocolNameInternal(number & 0xff);
+ }
+
+ private static String getProtocolNameInternal(int number) {
+ for (IPProtocols proto : IPProtocols.values()) {
+ if (proto.protocolNumber == number) {
+ return proto.toString();
+ }
+ }
+ //TODO: this is for backwards compatibility
+ return "0x" + Integer.toHexString(number);
+ }
+
+ public static short getProtocolNumberShort(String name) {
+ IPProtocols p = fromString(name);
+ if (p != null) {
+ return p.shortValue();
+ }
+ //This method should be called after validation only
+ throw new IllegalArgumentException("Illegal IP protocol value: " + name);
+ }
+
+ public static int getProtocolNumberInt(String name) {
+ IPProtocols p = fromString(name);
+ if (p != null) {
+ return p.intValue();
+ }
+ //This method should be called after validation only
+ throw new IllegalArgumentException("Illegal IP protocol value: " + name);
+ }
+
+ public static byte getProtocolNumberByte(String name) {
+ IPProtocols p = fromString(name);
+ if (p != null) {
+ return p.byteValue();
+ }
+ //This method should be called after validation only
+ throw new IllegalArgumentException("Illegal IP protocol value: " + name);
+ }
+
+ public static List<String> getProtocolNameList() {
+ List<String> protoList = new ArrayList<String>();
+ for (IPProtocols proto : IPProtocols.values()) {
+ protoList.add(proto.toString());
+ }
+ return protoList;
+ }
+
+ /**
+ * Method to parse an IPProtocol from a numeric string
+ *
+ * @param s
+ * The IP protocol string to be parsed
+ * @return The IP protocol Enum, or null if invalid protocol string is passed
+ */
+ public static IPProtocols fromString(String s) {
+ // null/empty/any/* evaluates to ANY
+ if (s == null || s.isEmpty() || s.equalsIgnoreCase("any") || s.equals("*")) {
+ return IPProtocols.ANY;
+ }
+
+ // Try parsing numeric and find the related ENUM
+ try {
+ int protoNum = Integer.decode(s);
+ for (IPProtocols protoEnum : IPProtocols.values()) {
+ if (protoEnum.protocolNumber == protoNum) {
+ return protoEnum;
+ }
+ }
+ // At this point it's an invalid number (i.e. out of range or not a valid proto num)
+ return null;
+ } catch (NumberFormatException nfe) {
+ // numeric failed try by NAME
+ try {
+ return valueOf(s);
+ } catch(IllegalArgumentException e) {
+ // Neither numeric nor enum NAME, attempt human readable name
+ for (IPProtocols protoEnum : IPProtocols.values()) {
+ if (protoEnum.toString().equalsIgnoreCase(s)) {
+ return protoEnum;
+ }
+ }
+ //couldn't parse, signifies an invalid proto field!
+ return null;
+ }
+
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.vpnservice.mdsalutil.packet;
+
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.BufferException;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.liblldp.PacketException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class that represents the IPv4 packet objects
+ */
+
+public class IPv4 extends Packet {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(IPv4.class);
+ private static final String VERSION = "Version";
+ private static final String HEADERLENGTH = "HeaderLength";
+ private static final String DIFFSERV = "DiffServ";
+ private static final String ECN = "ECN";
+ private static final String TOTLENGTH = "TotalLength";
+ private static final String IDENTIFICATION = "Identification";
+ private static final String FLAGS = "Flags";
+ private static final String FRAGOFFSET = "FragmentOffset";
+ private static final String TTL = "TTL";
+ private static final String PROTOCOL = "Protocol";
+ private static final String CHECKSUM = "Checksum";
+ private static final String SIP = "SourceIPAddress";
+ private static final String DIP = "DestinationIPAddress";
+ private static final String OPTIONS = "Options";
+
+ private static final int UNIT_SIZE_SHIFT = 2;
+ private static final int UNIT_SIZE = (1 << UNIT_SIZE_SHIFT);
+ private static final int MIN_HEADER_SIZE = 20;
+
+ public static final Map<Byte, Class<? extends Packet>> protocolClassMap;
+ static {
+ protocolClassMap = new HashMap<Byte, Class<? extends Packet>>();
+ protocolClassMap.put(IPProtocols.ICMP.byteValue(), ICMP.class);
+ protocolClassMap.put(IPProtocols.UDP.byteValue(), UDP.class);
+ protocolClassMap.put(IPProtocols.TCP.byteValue(), TCP.class);
+ }
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(VERSION, new ImmutablePair<Integer, Integer>(0, 4));
+ put(HEADERLENGTH, new ImmutablePair<Integer, Integer>(4, 4));
+ put(DIFFSERV, new ImmutablePair<Integer, Integer>(8, 6));
+ put(ECN, new ImmutablePair<Integer, Integer>(14, 2));
+ put(TOTLENGTH, new ImmutablePair<Integer, Integer>(16, 16));
+ put(IDENTIFICATION, new ImmutablePair<Integer, Integer>(32, 16));
+ put(FLAGS, new ImmutablePair<Integer, Integer>(48, 3));
+ put(FRAGOFFSET, new ImmutablePair<Integer, Integer>(51, 13));
+ put(TTL, new ImmutablePair<Integer, Integer>(64, 8));
+ put(PROTOCOL, new ImmutablePair<Integer, Integer>(72, 8));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(80, 16));
+ put(SIP, new ImmutablePair<Integer, Integer>(96, 32));
+ put(DIP, new ImmutablePair<Integer, Integer>(128, 32));
+ put(OPTIONS, new ImmutablePair<Integer, Integer>(160, 0));
+ }
+ };
+
+ private final Map<String, byte[]> fieldValues;
+
+
+ /**
+ * Default constructor that sets the version to 4, headerLength to 5,
+ * and flags to 2. The default value for the identification is set to a
+ * random number and the remaining fields are set to 0.
+ */
+ public IPv4() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ corrupted = false;
+
+ setVersion((byte) 4);
+ setHeaderLength((byte) 5);
+ setDiffServ((byte) 0);
+ setECN((byte) 0);
+ setIdentification(generateId());
+ setFlags((byte) 2);
+ setFragmentOffset((short) 0);
+ }
+
+ /**
+ * The write access to the packet is set in this constructor.
+ * Constructor that sets the version to 4, headerLength to 5,
+ * and flags to 2. The default value for the identification is set to a
+ * random number and the remaining fields are set to 0.
+ * @param writeAccess - boolean
+ */
+ public IPv4(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ corrupted = false;
+
+ setVersion((byte) 4);
+ setHeaderLength((byte) 5);
+ setDiffServ((byte) 0);
+ setECN((byte) 0);
+ setIdentification(generateId());
+ setFlags((byte) 2);
+ setFragmentOffset((short) 0);
+ }
+
+ /**
+ * Gets the IP version stored
+ * @return the version
+ */
+ public byte getVersion() {
+ return (BitBufferHelper.getByte(fieldValues.get(VERSION)));
+ }
+
+ /**
+ * Gets the IP header length stored
+ * @return the headerLength in bytes
+ */
+ public int getHeaderLen() {
+ return (4 * BitBufferHelper.getByte(fieldValues.get(HEADERLENGTH)));
+ }
+
+ /**
+ * Gets the header size in bits
+ * @return The number of bits constituting the header
+ */
+ @Override
+ public int getHeaderSize() {
+ int headerLen = this.getHeaderLen();
+ if (headerLen == 0) {
+ headerLen = MIN_HEADER_SIZE;
+ }
+
+ return headerLen * NetUtils.NumBitsInAByte;
+ }
+
+ /**
+ * Gets the differential services value stored
+ * @return the diffServ
+ */
+ public byte getDiffServ() {
+ return BitBufferHelper.getByte(fieldValues.get(DIFFSERV));
+ }
+
+ /**
+ * Gets the ecn bits stored
+ * @return the ecn bits
+ */
+ public byte getECN() {
+ return BitBufferHelper.getByte(fieldValues.get(ECN));
+ }
+
+ /**
+ * Gets the total length of the IP header in bytes
+ * @return the totalLength
+ */
+ public short getTotalLength() {
+ return (BitBufferHelper.getShort(fieldValues.get(TOTLENGTH)));
+ }
+
+ /**
+ * Gets the identification value stored
+ * @return the identification
+ */
+ public short getIdentification() {
+ return (BitBufferHelper.getShort(fieldValues.get(IDENTIFICATION)));
+ }
+
+ /**
+ * Gets the flag values stored
+ * @return the flags
+ */
+ public byte getFlags() {
+ return (BitBufferHelper.getByte(fieldValues.get(FLAGS)));
+ }
+
+ /**
+ * Gets the TTL value stored
+ * @return the ttl
+ */
+ public byte getTtl() {
+ return (BitBufferHelper.getByte(fieldValues.get(TTL)));
+ }
+
+ /**
+ * Gets the protocol value stored
+ * @return the protocol
+ */
+ public byte getProtocol() {
+ return (BitBufferHelper.getByte(fieldValues.get(PROTOCOL)));
+ }
+
+ /**
+ * Gets the checksum value stored
+ * @return the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
+ }
+
+ /**
+ * Gets the fragment offset stored
+ * @return the fragmentOffset
+ */
+ public short getFragmentOffset() {
+ return (BitBufferHelper.getShort(fieldValues.get(FRAGOFFSET)));
+ }
+
+ /**
+ * Gets the source IP address stored
+ * @return the sourceAddress
+ */
+ public int getSourceAddress() {
+ return (BitBufferHelper.getInt(fieldValues.get(SIP)));
+ }
+
+ /**
+ * Gets the destination IP address stored
+ * @return the destinationAddress
+ */
+ public int getDestinationAddress() {
+ return (BitBufferHelper.getInt(fieldValues.get(DIP)));
+ }
+
+ /**
+ * gets the Options stored
+ * @return the options
+ */
+ public byte[] getOptions() {
+ return (fieldValues.get(OPTIONS));
+ }
+
+ @Override
+ /**
+ * Stores the value of fields read from data stream
+ * Variable header value like payload protocol, is stored here
+ * @param headerField
+ * @param readValue
+ */
+ public void setHeaderField(String headerField, byte[] readValue) {
+ if (headerField.equals(PROTOCOL)) {
+ // Don't set payloadClass if framgment offset is not zero.
+ byte[] fragoff = hdrFieldsMap.get(FRAGOFFSET);
+ if (fragoff == null || BitBufferHelper.getShort(fragoff) == 0) {
+ payloadClass = protocolClassMap.get(readValue[0]);
+ }
+ } else if (headerField.equals(FRAGOFFSET)) {
+ if (readValue != null && BitBufferHelper.getShort(readValue) != 0) {
+ // Clear payloadClass because protocol header is not present
+ // in this packet.
+ payloadClass = null;
+ }
+ } else if (headerField.equals(OPTIONS) &&
+ (readValue == null || readValue.length == 0)) {
+ hdrFieldsMap.remove(headerField);
+ return;
+ }
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ /**
+ * Stores the IP version from the header
+ * @param ipVersion the version to set
+ * @return IPv4
+ */
+ public IPv4 setVersion(byte ipVersion) {
+ byte[] version = BitBufferHelper.toByteArray(ipVersion);
+ fieldValues.put(VERSION, version);
+ return this;
+ }
+
+ /**
+ * Stores the length of IP header in words (4 bytes)
+ * @param ipheaderLength the headerLength to set
+ * @return IPv4
+ */
+ public IPv4 setHeaderLength(byte ipheaderLength) {
+ byte[] headerLength = BitBufferHelper.toByteArray(ipheaderLength);
+ fieldValues.put(HEADERLENGTH, headerLength);
+ return this;
+ }
+
+ /**
+ * Stores the differential services value from the IP header
+ * @param ipdiffServ the diffServ to set
+ * @return IPv4
+ */
+ public IPv4 setDiffServ(byte ipdiffServ) {
+ byte[] diffServ = BitBufferHelper.toByteArray(ipdiffServ);
+ fieldValues.put(DIFFSERV, diffServ);
+ return this;
+ }
+
+ /**
+ * Stores the ECN bits from the header
+ * @param ecn ECN bits to set
+ * @return IPv4
+ */
+ public IPv4 setECN(byte ecn) {
+ byte[] ecnbytes = BitBufferHelper.toByteArray(ecn);
+ fieldValues.put(ECN, ecnbytes);
+ return this;
+ }
+
+ /**
+ * Stores the total length of IP header in bytes
+ * @param iptotalLength the totalLength to set
+ * @return IPv4
+ */
+ public IPv4 setTotalLength(short iptotalLength) {
+ byte[] totalLength = BitBufferHelper.toByteArray(iptotalLength);
+ fieldValues.put(TOTLENGTH, totalLength);
+ return this;
+ }
+
+ /**
+ * Stores the identification number from the header
+ * @param ipIdentification the identification to set
+ * @return IPv4
+ */
+ public IPv4 setIdentification(short ipIdentification) {
+ byte[] identification = BitBufferHelper.toByteArray(ipIdentification);
+ fieldValues.put(IDENTIFICATION, identification);
+ return this;
+ }
+
+ /**
+ * Stores the IP flags value
+ * @param ipFlags the flags to set
+ * @return IPv4
+ */
+ public IPv4 setFlags(byte ipFlags) {
+ byte[] flags = { ipFlags };
+ fieldValues.put(FLAGS, flags);
+ return this;
+ }
+
+ /**
+ * Stores the IP fragmentation offset value
+ * @param ipFragmentOffset the fragmentOffset to set
+ * @return IPv4
+ */
+ public IPv4 setFragmentOffset(short ipFragmentOffset) {
+ byte[] fragmentOffset = BitBufferHelper.toByteArray(ipFragmentOffset);
+ fieldValues.put(FRAGOFFSET, fragmentOffset);
+ return this;
+ }
+
+ /**
+ * Stores the TTL value
+ * @param ipTtl the ttl to set
+ * @return IPv4
+ */
+ public IPv4 setTtl(byte ipTtl) {
+ byte[] ttl = BitBufferHelper.toByteArray(ipTtl);
+ fieldValues.put(TTL, ttl);
+ return this;
+ }
+
+ /**
+ * Stores the protocol value of the IP payload
+ * @param ipProtocol the protocol to set
+ * @return IPv4
+ */
+ public IPv4 setProtocol(byte ipProtocol) {
+ byte[] protocol = BitBufferHelper.toByteArray(ipProtocol);
+ fieldValues.put(PROTOCOL, protocol);
+ return this;
+ }
+
+ /**
+ * @param checksum the checksum to set
+ */
+ /*public IPv4 setChecksum() {
+ short ipChecksum = computeChecksum();
+ byte[] checksum = BitBufferHelper.toByteArray(ipChecksum);
+ fieldValues.put(CHECKSUM, checksum);
+ return this;
+ }*/
+
+ /**
+ * Stores the IP source address from the header
+ * @param ipSourceAddress the sourceAddress to set
+ * @return IPv4
+ */
+ public IPv4 setSourceAddress(InetAddress ipSourceAddress) {
+ byte[] sourceAddress = ipSourceAddress.getAddress();
+ fieldValues.put(SIP, sourceAddress);
+ return this;
+ }
+
+ /**
+ * Stores the IP destination address from the header
+ * @param ipDestinationAddress the destination Address to set
+ * @return IPv4
+ */
+ public IPv4 setDestinationAddress(InetAddress ipDestinationAddress) {
+ byte[] sourceAddress = ipDestinationAddress.getAddress();
+ fieldValues.put(DIP, sourceAddress);
+ return this;
+ }
+
+ /**
+ * Stores the IP destination address from the header
+ * @param ipDestinationAddress the destinationAddress to set
+ * @return IPv4
+ */
+ public IPv4 setDestinationAddress(int ipDestinationAddress) {
+ byte[] destinationAddress = BitBufferHelper
+ .toByteArray(ipDestinationAddress);
+ fieldValues.put(DIP, destinationAddress);
+ return this;
+ }
+
+ /**
+ * Generate a random number to set the Identification field
+ * in IPv4 Header
+ * @return short
+ */
+ private short generateId() {
+ Random randomgen = new Random();
+ return (short) (randomgen.nextInt(Short.MAX_VALUE + 1));
+ }
+
+ /**
+ * Store the options from IP header
+ * @param options - byte[]
+ * @return IPv4
+ */
+ public IPv4 setOptions(byte[] options) {
+ byte newIHL = (byte)(MIN_HEADER_SIZE >>> UNIT_SIZE_SHIFT);
+ if (options == null || options.length == 0) {
+ fieldValues.remove(OPTIONS);
+ } else {
+ int len = options.length;
+ int rlen = (len + (UNIT_SIZE - 1)) & ~(UNIT_SIZE - 1);
+ if (rlen > len) {
+ // Padding is required.
+ byte[] newopt = new byte[rlen];
+ System.arraycopy(options, 0, newopt, 0, len);
+ options = newopt;
+ len = rlen;
+ }
+ fieldValues.put(OPTIONS, options);
+ newIHL += (len >>> UNIT_SIZE_SHIFT);
+ }
+
+ setHeaderLength(newIHL);
+
+ return this;
+ }
+
+ /**
+ * Computes the IPv4 header checksum on the passed stream of bytes
+ * representing the packet
+ *
+ * @param data
+ * The byte stream
+ * @param offset
+ * The byte offset from where the IPv4 packet starts
+ * @return The computed checksum
+ */
+ short computeChecksum(byte[] data, int start) {
+ int end = start + getHeaderLen();
+ short checkSum = (short) 0;
+ int sum = 0, carry = 0, finalSum = 0;
+ int wordData;
+ int checksumStart = start
+ + (getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte);
+
+ for (int i = start; i <= (end - 1); i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ if (i == checksumStart) {
+ continue;
+ }
+ wordData = ((data[i] << 8) & 0xFF00) + (data[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+ carry = (sum >> 16) & 0xFF;
+ finalSum = (sum & 0xFFFF) + carry;
+ checkSum = (short) ~((short) finalSum & 0xFFFF);
+
+ return checkSum;
+ }
+
+ @Override
+ /**
+ * Gets the number of bits for the fieldname specified
+ * If the fieldname has variable length like "Options", then this value is computed using the header length
+ * @param fieldname - String
+ * @return number of bits for fieldname - int
+ */
+ public int getfieldnumBits(String fieldName) {
+ if (fieldName.equals(OPTIONS)) {
+ return (getHeaderLen() - MIN_HEADER_SIZE) * NetUtils.NumBitsInAByte;
+ }
+ return hdrFieldCoordMap.get(fieldName).getRight();
+ }
+
+ @Override
+ /**
+ * Method to perform post serialization - like computation of checksum of serialized header
+ * @param data
+ * @return void
+ * @Exception throws PacketException
+ */
+ protected void postSerializeCustomOperation(byte[] data)
+ throws PacketException {
+
+ // Recompute the total length field here
+ byte[] totalLength = BitBufferHelper.toByteArray((short) data.length);
+ try {
+ BitBufferHelper.setBytes(data, totalLength, getfieldOffset(TOTLENGTH),
+ getfieldnumBits(TOTLENGTH));
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+
+ // Now compute the Header Checksum
+ byte[] checkSum = BitBufferHelper.toByteArray(computeChecksum(data, 0));
+
+ try {
+ BitBufferHelper.setBytes(data, checkSum, getfieldOffset(CHECKSUM),
+ getfieldnumBits(CHECKSUM));
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+ }
+
+ @Override
+ /**
+ * Stores the payload of IP, serializes it and stores the length of serialized payload
+ * bytes in Total Length
+ * @param payload - Packet
+ */
+ /**
+ * Set the total length field in the IPv4 Object
+ * Note: this field will get overwritten during serialization phase.
+ */
+ public void setPayload(Packet payload) {
+ this.payload = payload;
+ /*
+ * Deriving the Total Length here
+ */
+ int payloadLength = 0;
+ if (payload != null) {
+ try {
+ payloadLength = payload.serialize().length;
+ } catch (PacketException e) {
+ logger.error("", e);
+ }
+ }
+
+ this.setTotalLength((short) (this.getHeaderLen() + payloadLength));
+ }
+
+
+ /**
+ * Method to perform post deserialization - like compare computed checksum with
+ * the one obtained from IP header
+ */
+ @Override
+ protected void postDeserializeCustomOperation(byte[] data, int startBitOffset) {
+ int start = startBitOffset / NetUtils.NumBitsInAByte;
+ short computedChecksum = computeChecksum(data, start);
+ short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
+ if (computedChecksum != actualChecksum) {
+ corrupted = true;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.vpnservice.mdsalutil.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.Packet;
+
+/**
+ * Class that represents the TCP segment objects
+ */
+public class TCP extends Packet {
+
+ public static final String SRCPORT = "SourcePort";
+ public static final String DESTPORT = "DestinationPort";
+ public static final String SEQNUMBER = "SequenceNumber";
+ public static final String ACKNUMBER = "AcknowledgementNumber";
+ public static final String DATAOFFSET = "DataOffset";
+ public static final String RESERVED = "Reserved";
+ public static final String HEADERLENFLAGS = "HeaderLenFlags";
+ public static final String WINDOWSIZE = "WindowSize";
+ public static final String CHECKSUM = "Checksum";
+ public static final String URGENTPOINTER = "UrgentPointer";
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(SRCPORT, new ImmutablePair<Integer, Integer>(0, 16));
+ put(DESTPORT, new ImmutablePair<Integer, Integer>(16, 16));
+ put(SEQNUMBER, new ImmutablePair<Integer, Integer>(32, 32));
+ put(ACKNUMBER, new ImmutablePair<Integer, Integer>(64, 32));
+ put(DATAOFFSET, new ImmutablePair<Integer, Integer>(96, 4));
+ put(RESERVED, new ImmutablePair<Integer, Integer>(100, 3));
+ put(HEADERLENFLAGS, new ImmutablePair<Integer, Integer>(103, 9));
+ put(WINDOWSIZE, new ImmutablePair<Integer, Integer>(112, 16));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(128, 16));
+ put(URGENTPOINTER, new ImmutablePair<Integer, Integer>(144, 16));
+ }
+ };
+
+ private final Map<String, byte[]> fieldValues;
+
+ /**
+ * Default constructor that sets all the header fields to zero
+ */
+ public TCP() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ /* Setting all remaining header field values to
+ * default value of 0. These maybe changed as needed
+ */
+ setSourcePort((short) 0);
+ setDestinationPort((short) 0);
+ setSequenceNumber(0);
+ setAckNumber(0);
+ setDataOffset((byte) 0);
+ setReserved((byte) 0);
+ setWindowSize((short) 0);
+ setUrgentPointer((short) 0);
+ setChecksum((short) 0);
+ }
+
+ /**
+ * Constructor that sets the access level for the packet and
+ * sets all the header fields to zero.
+ * @param writeAccess - boolean
+ */
+ public TCP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ /* Setting all remaining header field values to
+ * default value of 0. These maybe changed as needed
+ */
+ setSourcePort((short) 0);
+ setDestinationPort((short) 0);
+ setSequenceNumber(0);
+ setAckNumber(0);
+ setDataOffset((byte) 0);
+ setReserved((byte) 0);
+ setWindowSize((short) 0);
+ setUrgentPointer((short) 0);
+ setChecksum((short) 0);
+ }
+
+ @Override
+ /**
+ * Stores the value read from data stream
+ * @param headerField - String
+ * @param readValue - byte[]
+ */
+ public void setHeaderField(String headerField, byte[] readValue) {
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ /**
+ * Sets the TCP source port for the current TCP object instance
+ * @param tcpSourcePort short
+ * @return TCP
+ */
+ public TCP setSourcePort(short tcpSourcePort) {
+ byte[] sourcePort = BitBufferHelper.toByteArray(tcpSourcePort);
+ fieldValues.put(SRCPORT, sourcePort);
+ return this;
+ }
+
+ /**
+ * Sets the TCP destination port for the current TCP object instance
+ * @param tcpDestinationPort short
+ * @return TCP
+ */
+ public TCP setDestinationPort(short tcpDestinationPort) {
+ byte[] destinationPort = BitBufferHelper
+ .toByteArray(tcpDestinationPort);
+ fieldValues.put(DESTPORT, destinationPort);
+ return this;
+ }
+
+ /**
+ * Sets the TCP sequence number for the current TCP object instance
+ * @param tcpSequenceNumber - int
+ * @return TCP
+ */
+ public TCP setSequenceNumber(int tcpSequenceNumber) {
+ byte[] sequenceNumber = BitBufferHelper.toByteArray(tcpSequenceNumber);
+ fieldValues.put(SEQNUMBER, sequenceNumber);
+ return this;
+ }
+
+ /**
+ * Sets the TCP data offset for the current TCP object instance
+ * @param tcpDataOffset - byte
+ * @return TCP
+ */
+ public TCP setDataOffset(byte tcpDataOffset) {
+ byte[] offset = BitBufferHelper.toByteArray(tcpDataOffset);
+ fieldValues.put("DataOffset", offset);
+ return this;
+ }
+
+ /**
+ * Sets the TCP reserved bits for the current TCP object instance
+ * @param tcpReserved byte
+ * @return TCP
+ */
+ public TCP setReserved(byte tcpReserved) {
+ byte[] reserved = BitBufferHelper.toByteArray(tcpReserved);
+ fieldValues.put("Reserved", reserved);
+ return this;
+ }
+
+ /**
+ * Sets the TCP Ack number for the current TCP object instance
+ * @param tcpAckNumber int
+ * @return TCP
+ */
+ public TCP setAckNumber(int tcpAckNumber) {
+ byte[] ackNumber = BitBufferHelper.toByteArray(tcpAckNumber);
+ fieldValues.put(ACKNUMBER, ackNumber);
+ return this;
+ }
+
+ /**
+ * Sets the TCP flags for the current TCP object instance
+ * @param tcpFlags short
+ * @return TCP
+ */
+ public TCP setHeaderLenFlags(short tcpFlags) {
+ byte[] headerLenFlags = BitBufferHelper.toByteArray(tcpFlags);
+ fieldValues.put(HEADERLENFLAGS, headerLenFlags);
+ return this;
+ }
+
+ /**
+ * Sets the TCP window size for the current TCP object instance
+ * @param tcpWsize short
+ * @return TCP
+ */
+ public TCP setWindowSize(short tcpWsize) {
+ byte[] wsize = BitBufferHelper.toByteArray(tcpWsize);
+ fieldValues.put(WINDOWSIZE, wsize);
+ return this;
+ }
+
+ /**
+ * Sets the TCP checksum for the current TCP object instance
+ * @param tcpChecksum short
+ * @return TCP
+ */
+ public TCP setChecksum(short tcpChecksum) {
+ byte[] checksum = BitBufferHelper.toByteArray(tcpChecksum);
+ fieldValues.put(CHECKSUM, checksum);
+ return this;
+ }
+
+ /**
+ * Sets the TCP Urgent Pointer for the current TCP object instance
+ * @param tcpUrgentPointer short
+ * @return TCP
+ */
+ public TCP setUrgentPointer(short tcpUrgentPointer) {
+ byte[] urgentPointer = BitBufferHelper.toByteArray(tcpUrgentPointer);
+ fieldValues.put(URGENTPOINTER, urgentPointer);
+ return this;
+ }
+
+ /**
+ * Gets the stored source port value of TCP header
+ * @return the sourcePort
+ */
+ public short getSourcePort() {
+ return (BitBufferHelper.getShort(fieldValues.get(SRCPORT)));
+ }
+
+ /**
+ * Gets the stored destination port value of TCP header
+ * @return the destinationPort
+ */
+ public short getDestinationPort() {
+ return (BitBufferHelper.getShort(fieldValues.get(DESTPORT)));
+ }
+
+ /**
+ * Get the stored checksum value of the TCP header
+ * @return short - the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
+ }
+
+}
--- /dev/null
+/*
+ * 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.vpnservice.mdsalutil.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.Packet;
+
+/**
+ * Class that represents the UDP datagram objects
+ */
+
+public class UDP extends Packet {
+
+ private static final String SRCPORT = "SourcePort";
+ private static final String DESTPORT = "DestinationPort";
+ private static final String LENGTH = "Length";
+ private static final String CHECKSUM = "Checksum";
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(SRCPORT, new ImmutablePair<Integer, Integer>(0, 16));
+ put(DESTPORT, new ImmutablePair<Integer, Integer>(16, 16));
+ put(LENGTH, new ImmutablePair<Integer, Integer>(32, 16));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(48, 16));
+ }
+ };
+
+ public UDP() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ /* Setting all remaining header field values to
+ * default value of 0. These maybe changed as needed
+ */
+ setSourcePort((short) 0);
+ setDestinationPort((short) 0);
+ setChecksum((short) 0);
+ }
+
+ public UDP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ /* Setting all remaining header field values to
+ * default value of 0. These maybe changed as needed
+ */
+ setSourcePort((short) 0);
+ setDestinationPort((short) 0);
+ setChecksum((short) 0);
+ }
+
+ private final Map<String, byte[]> fieldValues;
+
+ /* public static Map<Short, Class<? extends Packet>> decodeMap;
+
+ static {
+ decodeMap = new HashMap<Short, Class<? extends Packet>>();
+ UDP.decodeMap.put((short)67, DHCP.class);
+ UDP.decodeMap.put((short)68, DHCP.class);
+ }*/
+ /**
+ * Get the stored source port
+ * @return short - the sourcePort
+ */
+ public short getSourcePort() {
+ return (BitBufferHelper.getShort(fieldValues.get(SRCPORT)));
+ }
+
+ /**
+ * Get the stored destination port
+ * @return short - the destinationPort
+ */
+ public short getDestinationPort() {
+ return (BitBufferHelper.getShort(fieldValues.get(DESTPORT)));
+ }
+
+ /**
+ * Gets the stored length of UDP header
+ * @return short - the length
+ */
+ public short getLength() {
+ return (BitBufferHelper.getShort(fieldValues.get(LENGTH)));
+ }
+
+ /**
+ * Get the stored checksum value of the UDP header
+ * @return short - the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
+ }
+
+ @Override
+ /**
+ * Store the value read from data stream in hdrFieldMap
+ */
+ public void setHeaderField(String headerField, byte[] readValue) {
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ /**
+ * Sets the sourcePort value for the current UDP object instance
+ * @param udpSourcePort short source port to set
+ * @return UDP
+ */
+ public UDP setSourcePort(short udpSourcePort) {
+ byte[] sourcePort = BitBufferHelper.toByteArray(udpSourcePort);
+ fieldValues.put(SRCPORT, sourcePort);
+ return this;
+ }
+
+ /**
+ * Sets the destinationPort value for the current UDP object instance
+ * @param udpDestinationPort short destination port to set
+ * @return UDP
+ */
+ public UDP setDestinationPort(short udpDestinationPort) {
+ byte[] destinationPort = BitBufferHelper
+ .toByteArray(udpDestinationPort);
+ fieldValues.put(DESTPORT, destinationPort);
+ return this;
+ }
+
+ /**
+ * Set the UDP header length value for the current UDP object instance
+ * @param udpLength - short - the length to set
+ * @return UDP
+ */
+ public UDP setLength(short udpLength) {
+ byte[] length = BitBufferHelper.toByteArray(udpLength);
+ fieldValues.put(LENGTH, length);
+ return this;
+ }
+
+ /**
+ * Set the checksum for the current UDP object instance
+ * @param udpChecksum - short - the checksum to set
+ * @return UDP
+ */
+ public UDP setChecksum(short udpChecksum) {
+ byte[] checksum = BitBufferHelper.toByteArray(udpChecksum);
+ fieldValues.put(CHECKSUM, checksum);
+ return this;
+ }
+
+}