package org.openflow.protocol.action;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import org.openflow.util.HexString;
public class ActionVendorOutputNextHop extends OFActionVendor {
private static final long serialVersionUID = 1L;
private static int VENDOR_CISCO = 0xC;
private enum ONHLength {
ONH_LEN_MIN(16),
ONH_LEN_P2P(16),
ONH_LEN_IPV4(24),
ONH_LEN_MAC(32),
ONH_LEN_IPV6(40);
private int value;
private ONHLength(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
private enum ONHActionType {
ONH_ACTION_NONE(0),
ONH_ACTION_OUTPUT_NH(1),
ONH_ACTION_NETFLOW(2);
private int value;
private ONHActionType(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
private enum ONHAddressType {
ONH_ADDRTYPE_NONE(0),
ONH_ADDRTYPE_P2P(1),
ONH_ADDRTYPE_IPV4(2),
ONH_ADDRTYPE_IPV6(3),
ONH_ADDRTYPE_MAC48(4);
private int value;
private ONHAddressType(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
private enum ONHXAddressType {
ONH_XADDRTYPE_NONE(0),
ONH_XADDRTYPE_PORT(1),
ONH_XADDRTYPE_VPNID(2);
private int value;
private ONHXAddressType(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
protected InetAddress address;
public ActionVendorOutputNextHop() {
super();
super.setLength((short)ONHLength.ONH_LEN_MIN.getValue());
super.setVendor(VENDOR_CISCO);
this.address = null;
}
public void setNextHop(InetAddress address) {
short actionLen;
if (address instanceof Inet4Address)
actionLen = (short)ONHLength.ONH_LEN_IPV4.getValue();
else
actionLen = (short)ONHLength.ONH_LEN_IPV6.getValue();
super.setLength(actionLen);
this.address = address;
}
public InetAddress getNextHop() {
return this.address;
}
@Override
public void readFrom(ByteBuffer data) {
/*
* For now, only contains the next hop address
*/
//super.readFrom(data); don't need this
if (data.remaining() < super.getLength()-8) {
/*
* malformed element, skip over
*/
data.position(data.remaining());
return;
}
if ((super.getLength() != (short)ONHLength.ONH_LEN_IPV4.getValue()) &&
(super.getLength() != (short)ONHLength.ONH_LEN_IPV6.getValue())) {
/*
* mal-formed element, skip over
*/
data.position(super.getLength());
return;
}
data.getShort(); // skip the ONH_ACTION_OUTPUT_NH
data.getShort(); // skip address and xtraaddress types
data.getInt(); // skip the extra address (8 bytes)
data.getInt();
byte[] a;
if (super.getLength() == (short)ONHLength.ONH_LEN_IPV4.getValue()) {
a = new byte[4];
data.get(a);
} else {
a = new byte[16];
data.get(a);
data.getInt(); //4 bytes pad
}
try {
this.address = InetAddress.getByAddress(a);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
@Override
public void writeTo(ByteBuffer data) {
byte atype = (byte)(ONHAddressType.ONH_ADDRTYPE_NONE.getValue());
byte xatype = (byte)(ONHXAddressType.ONH_XADDRTYPE_NONE.getValue());
if (address instanceof Inet4Address)
atype = (byte)(ONHAddressType.ONH_ADDRTYPE_IPV4.getValue());
else
atype = (byte)(ONHAddressType.ONH_ADDRTYPE_IPV6.getValue());
super.writeTo(data); // this writes the standard 8byte ofp_action_vendor_header
data.putShort((short)(ONHActionType.ONH_ACTION_OUTPUT_NH.getValue()));
data.put(atype);
data.put(xatype);
/*
* write the xtra address. For now it is all 0
*/
data.putInt(0); // 8-byte pad
data.putInt(0);
/*
* write the address only when address type is not P2P
*/
if (atype == (byte)(ONHAddressType.ONH_ADDRTYPE_IPV4.getValue())) {
data.put(address.getAddress()); // no need to pad
//avnh.put(address.getAddress());
} else if (atype == (byte)(ONHAddressType.ONH_ADDRTYPE_IPV6.getValue())) {
data.put(address.getAddress());
//avnh.put(address.getAddress());
data.putInt(0); // 4-byte pad
//avnh.putInt(0);
}
ActionVendorOutputNextHop a = new ActionVendorOutputNextHop();
a.setLength((short)24);
}
@Override
public int hashCode() {
final int prime = 347;
int result = super.hashCode();
result = prime * result + address.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof ActionVendorOutputNextHop)) {
return false;
}
ActionVendorOutputNextHop other = (ActionVendorOutputNextHop) obj;
if (!other.address.equals(this.address))
return false;
return true;
}
public String toString() {
return ("OutputNextHop: " + address.getHostAddress());
}
}