/*
* Copyright (c) 2013 Pantheon Technologies s.r.o. 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.openflowjava.protocol.impl.deserialization.factories;
import io.netty.buffer.ByteBuf;
import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
import org.opendaylight.openflowjava.util.ExperimenterDeserializerKeyFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.BadActionCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.BadInstructionCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.BadMatchCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.BadRequestCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ErrorType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupModFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.HelloFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterModFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortModFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.QueueOpFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.RoleRequestFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.SwitchConfigFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableModFailedCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
/**
* Translates Error messages
* @author michal.polkorab
* @author timotej.kubas
*/
public class ErrorMessageFactory implements OFDeserializer<ErrorMessage>,
DeserializerRegistryInjector {
private static final String UNKNOWN_CODE = "UNKNOWN_CODE";
private static final String UNKNOWN_TYPE = "UNKNOWN_TYPE";
private DeserializerRegistry registry;
@Override
public ErrorMessage deserialize(ByteBuf rawMessage) {
int startIndex = rawMessage.readerIndex();
ErrorMessageBuilder builder = new ErrorMessageBuilder();
builder.setVersion((short) EncodeConstants.OF13_VERSION_ID);
builder.setXid(rawMessage.readUnsignedInt());
int type = rawMessage.readUnsignedShort();
ErrorType errorType = ErrorType.forValue(type);
if (ErrorType.EXPERIMENTER.equals(errorType)) {
OFDeserializer<ErrorMessage> deserializer = registry.getDeserializer(
ExperimenterDeserializerKeyFactory.createExperimenterErrorDeserializerKey(
EncodeConstants.OF13_VERSION_ID, rawMessage.getUnsignedInt(
rawMessage.readerIndex() + EncodeConstants.SIZE_OF_SHORT_IN_BYTES)));
rawMessage.readerIndex(startIndex);
return deserializer.deserialize(rawMessage);
}
decodeType(builder, errorType, type);
decodeCode(rawMessage, builder, errorType);
int remainingBytes = rawMessage.readableBytes();
if (remainingBytes > 0) {
byte[] data = new byte[remainingBytes];
rawMessage.readBytes(data);
builder.setData(data);
}
return builder.build();
}
private static void decodeType(ErrorMessageBuilder builder, ErrorType type, int readValue) {
if (type != null) {
builder.setType(type.getIntValue());
builder.setTypeString(type.name());
} else {
builder.setType(readValue);
builder.setTypeString(UNKNOWN_TYPE);
}
}
private static void decodeCode(ByteBuf rawMessage, ErrorMessageBuilder builder,
ErrorType type) {
int code = rawMessage.readUnsignedShort();
if (type != null) {
switch (type) {
case HELLOFAILED:
{
HelloFailedCode errorCode = HelloFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case BADREQUEST:
{
BadRequestCode errorCode = BadRequestCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case BADACTION:
{
BadActionCode errorCode = BadActionCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case BADINSTRUCTION:
{
BadInstructionCode errorCode = BadInstructionCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case BADMATCH:
{
BadMatchCode errorCode = BadMatchCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case FLOWMODFAILED:
{
FlowModFailedCode errorCode = FlowModFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case GROUPMODFAILED:
{
GroupModFailedCode errorCode = GroupModFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case PORTMODFAILED:
{
PortModFailedCode errorCode = PortModFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case TABLEMODFAILED:
{
TableModFailedCode errorCode = TableModFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case QUEUEOPFAILED:
{
QueueOpFailedCode errorCode = QueueOpFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case SWITCHCONFIGFAILED:
{
SwitchConfigFailedCode errorCode = SwitchConfigFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case ROLEREQUESTFAILED:
{
RoleRequestFailedCode errorCode = RoleRequestFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case METERMODFAILED:
{
MeterModFailedCode errorCode = MeterModFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
case TABLEFEATURESFAILED:
{
TableFeaturesFailedCode errorCode = TableFeaturesFailedCode.forValue(code);
if (errorCode != null) {
setCode(builder, errorCode.getIntValue(), errorCode.name());
} else {
setUnknownCode(builder, code);
}
break;
}
default:
setUnknownCode(builder, code);
break;
}
} else {
setUnknownCode(builder, code);
}
}
private static void setUnknownCode(ErrorMessageBuilder builder, int readValue) {
builder.setCode(readValue);
builder.setCodeString(UNKNOWN_CODE);
}
private static void setCode(ErrorMessageBuilder builder, int code, String codeString) {
builder.setCode(code);
builder.setCodeString(codeString);
}
@Override
public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
this.registry = deserializerRegistry;
}
}