org.opendaylight.openflowjava.nx.codec.action.LearnCodecUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.openflowjava.nx.codec.action.LearnCodecUtil.java

Source

/*
 * Copyright (c) 2016 Hewlett-Packard Enterprise 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.nx.codec.action;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import io.netty.buffer.ByteBuf;

import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromField;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValue;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoField;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoField;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LearnCodecUtil {

    private static final Logger logger = LoggerFactory.getLogger(LearnCodecUtil.class);
    public static final int HEADER_LENGTH = 32;
    private static final short SRC_MASK = 0x2000;
    private static final short DST_MASK = 0x1800;
    private static final short NUM_BITS_MASK = 0x07FF;
    private static final int SRC_POS = 13;
    private static final int DST_POS = 11;
    private static final int FROM_FIELD_LENGTH = 14;
    private static final int FROM_VALUE_LENGTH = 10;
    private static final int TO_PORT_LENGTH = 8;
    private static final int EMPTY_FLOW_MOD_LENGTH = 2;
    private static short length;

    static short deserializeHeader(ByteBuf message) {
        // size of experimenter type
        message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
        // size of length
        short length = message.readShort();
        // vendor id
        message.skipBytes(EncodeConstants.SIZE_OF_INT_IN_BYTES);
        // subtype
        message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
        return length;
    }

    /*
     *                                 SERIALIZATION
    */

    static void serializeLearnHeader(final ByteBuf outBuffer, ActionLearn action) {
        outBuffer.writeShort(action.getNxActionLearn().getIdleTimeout().shortValue());
        outBuffer.writeShort(action.getNxActionLearn().getHardTimeout().shortValue());
        outBuffer.writeShort(action.getNxActionLearn().getPriority().shortValue());
        outBuffer.writeLong(action.getNxActionLearn().getCookie().longValue());
        outBuffer.writeShort(action.getNxActionLearn().getFlags().shortValue());
        outBuffer.writeByte(action.getNxActionLearn().getTableId().byteValue());
        outBuffer.writeZero(1);
        outBuffer.writeShort(action.getNxActionLearn().getFinIdleTimeout().shortValue());
        outBuffer.writeShort(action.getNxActionLearn().getFinHardTimeout().shortValue());
    }

    static void serializeFlowMods(final ByteBuf outBuffer, ActionLearn action) {
        if (action.getNxActionLearn().getFlowMods() != null) {
            for (FlowMods flowMod : action.getNxActionLearn().getFlowMods()) {
                if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase) {
                    FlowModAddMatchFromField flowModSpecFromField = ((FlowModAddMatchFromFieldCase) flowMod
                            .getFlowModSpec()).getFlowModAddMatchFromField();
                    toFlowModSpecHeader(flowModSpecFromField, outBuffer);
                    outBuffer.writeInt(flowModSpecFromField.getSrcField().intValue());
                    outBuffer.writeShort(flowModSpecFromField.getSrcOfs().shortValue());
                    outBuffer.writeInt(flowModSpecFromField.getDstField().intValue());
                    outBuffer.writeShort(flowModSpecFromField.getDstOfs().shortValue());
                } else if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase) {
                    FlowModAddMatchFromValue flowModSpec = ((FlowModAddMatchFromValueCase) flowMod.getFlowModSpec())
                            .getFlowModAddMatchFromValue();
                    toFlowModSpecHeader(flowModSpec, outBuffer);
                    outBuffer.writeShort(flowModSpec.getValue().shortValue());
                    outBuffer.writeInt(flowModSpec.getSrcField().intValue());
                    outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());

                } else if (flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase) {
                    FlowModCopyFieldIntoField flowModSpec = ((FlowModCopyFieldIntoFieldCase) flowMod
                            .getFlowModSpec()).getFlowModCopyFieldIntoField();
                    toFlowModSpecHeader(flowModSpec, outBuffer);
                    outBuffer.writeInt(flowModSpec.getSrcField().intValue());
                    outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
                    outBuffer.writeInt(flowModSpec.getDstField().intValue());
                    outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());

                } else if (flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase) {
                    FlowModCopyValueIntoField flowModSpec = ((FlowModCopyValueIntoFieldCase) flowMod
                            .getFlowModSpec()).getFlowModCopyValueIntoField();
                    toFlowModSpecHeader(flowModSpec, outBuffer);
                    outBuffer.writeShort(flowModSpec.getValue().shortValue());
                    outBuffer.writeInt(flowModSpec.getDstField().intValue());
                    outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());

                } else if (flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase) {
                    FlowModOutputToPort flowModSpec = ((FlowModOutputToPortCase) flowMod.getFlowModSpec())
                            .getFlowModOutputToPort();
                    toFlowModSpecHeader(flowModSpec, outBuffer);
                    outBuffer.writeInt(flowModSpec.getSrcField().intValue());
                    outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
                }
            }
        }
    }

    private static void toFlowModSpecHeader(FlowModOutputToPort flowModSpec, ByteBuf outBuffer) {
        serializeFlowModSpecHeader(0, 2, (short) (int) flowModSpec.getFlowModNumBits(), outBuffer);
    }

    private static void toFlowModSpecHeader(FlowModCopyValueIntoField flowModSpec, ByteBuf outBuffer) {
        serializeFlowModSpecHeader(1, 1, (short) (int) flowModSpec.getFlowModNumBits(), outBuffer);
    }

    private static void toFlowModSpecHeader(FlowModCopyFieldIntoField flowModSpec, ByteBuf outBuffer) {
        serializeFlowModSpecHeader(0, 1, (short) (int) flowModSpec.getFlowModNumBits(), outBuffer);
    }

    private static void toFlowModSpecHeader(FlowModAddMatchFromValue flowModSpec, ByteBuf outBuffer) {
        serializeFlowModSpecHeader(1, 0, (short) (int) flowModSpec.getFlowModNumBits(), outBuffer);
    }

    private static void toFlowModSpecHeader(FlowModAddMatchFromField flowModSpec, ByteBuf outBuffer) {
        serializeFlowModSpecHeader(0, 0, (short) (int) flowModSpec.getFlowModNumBits(), outBuffer);
    }

    private static void serializeFlowModSpecHeader(int src, int dst, short bitNum, ByteBuf outBuffer) {
        short s = 0;
        s |= (src << SRC_POS);
        s |= (dst << DST_POS);
        s |= bitNum;
        outBuffer.writeShort(s);
    }

    static int calcLength(ActionLearn action) {
        int length = HEADER_LENGTH;
        if (action.getNxActionLearn().getFlowMods() == null) {
            return length;
        }
        for (FlowMods flowMod : action.getNxActionLearn().getFlowMods()) {
            if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase) {
                length += FROM_FIELD_LENGTH;
            } else if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase) {
                length += FROM_VALUE_LENGTH;
            } else if (flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase) {
                length += FROM_FIELD_LENGTH;
            } else if (flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase) {
                length += FROM_VALUE_LENGTH;
            } else if (flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase) {
                length += TO_PORT_LENGTH;
            }
        }

        return length;
    }

    /*
     *                                 DESERIALIZATION
    */

    static void deserializeLearnHeader(final ByteBuf message, NxActionLearnBuilder nxActionLearnBuilder) {
        nxActionLearnBuilder.setIdleTimeout(message.readUnsignedShort());
        nxActionLearnBuilder.setHardTimeout(message.readUnsignedShort());
        nxActionLearnBuilder.setPriority(message.readUnsignedShort());
        nxActionLearnBuilder.setCookie(BigInteger.valueOf(message.readLong()));
        nxActionLearnBuilder.setFlags(message.readUnsignedShort());
        nxActionLearnBuilder.setTableId(message.readUnsignedByte());
        message.skipBytes(1);
        nxActionLearnBuilder.setFinIdleTimeout(message.readUnsignedShort());
        nxActionLearnBuilder.setFinHardTimeout(message.readUnsignedShort());
    }

    static synchronized void buildFlowModSpecs(NxActionLearnBuilder nxActionLearnBuilder, ByteBuf message,
            short length) {
        LearnCodecUtil.length = length;
        List<FlowMods> flowModeList = new ArrayList<FlowMods>();

        while (LearnCodecUtil.length > 0) {
            FlowMods flowMod = readFlowMod(message);

            if (flowMod != null) {
                flowModeList.add(flowMod);
            } else {
                logger.trace("skipping padding bytes");
            }
        }

        if (LearnCodecUtil.length != 0) {
            logger.error("Learn Codec read " + Math.abs(length)
                    + " bytes more than needed from stream. Packet might be corrupted");
        }
        nxActionLearnBuilder.setFlowMods(flowModeList);
    }

    private static FlowMods readFlowMod(ByteBuf message) {
        short header = message.readShort();
        length -= EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
        if (header == 0) {
            return null;
        }

        short src = (short) ((header & SRC_MASK) >> SRC_POS);
        short dst = (short) ((header & DST_MASK) >> DST_POS);
        short numBits = (short) (header & NUM_BITS_MASK);

        if (src == 0 && dst == 0 && numBits != 0) {
            return readFlowModAddMatchFromField(message, numBits);
        } else if (src == 0 && dst == 0) {
            message.skipBytes(EMPTY_FLOW_MOD_LENGTH);
            length -= EMPTY_FLOW_MOD_LENGTH;
        } else if (src == 1 && dst == 0) {
            return readFlowModAddMatchFromValue(message, numBits);
        } else if (src == 0 && dst == 1) {
            return readFlowModCopyFromField(message, numBits);
        } else if (src == 1 && dst == 1) {
            return readFlowModCopyFromValue(message, numBits);
        } else if (src == 0 && dst == 2) {
            return readFlowToPort(message, numBits);
        }
        return null;
    }

    private static FlowMods readFlowModAddMatchFromField(ByteBuf message, short numBits) {
        FlowModAddMatchFromFieldBuilder builder = new FlowModAddMatchFromFieldBuilder();
        builder.setSrcField((long) message.readInt());
        builder.setSrcOfs((int) message.readShort());
        builder.setDstField((long) message.readInt());
        builder.setDstOfs((int) message.readShort());
        builder.setFlowModNumBits((int) numBits);
        length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;

        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
        FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder();
        caseBuilder.setFlowModAddMatchFromField(builder.build());
        flowModsBuilder.setFlowModSpec(caseBuilder.build());
        return flowModsBuilder.build();
    }

    private static FlowMods readFlowModAddMatchFromValue(ByteBuf message, short numBits) {
        FlowModAddMatchFromValueBuilder builder = new FlowModAddMatchFromValueBuilder();
        builder.setValue((int) message.readUnsignedShort());
        builder.setSrcField((long) message.readInt());
        builder.setSrcOfs((int) message.readShort());
        builder.setFlowModNumBits((int) numBits);
        length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;

        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
        FlowModAddMatchFromValueCaseBuilder caseBuilder = new FlowModAddMatchFromValueCaseBuilder();
        caseBuilder.setFlowModAddMatchFromValue(builder.build());
        flowModsBuilder.setFlowModSpec(caseBuilder.build());
        return flowModsBuilder.build();
    }

    private static FlowMods readFlowModCopyFromField(ByteBuf message, short numBits) {
        FlowModCopyFieldIntoFieldBuilder builder = new FlowModCopyFieldIntoFieldBuilder();
        builder.setSrcField((long) message.readInt());
        builder.setSrcOfs((int) message.readShort());
        builder.setDstField((long) message.readInt());
        builder.setDstOfs((int) message.readShort());
        builder.setFlowModNumBits((int) numBits);
        length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;

        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
        FlowModCopyFieldIntoFieldCaseBuilder caseBuilder = new FlowModCopyFieldIntoFieldCaseBuilder();
        caseBuilder.setFlowModCopyFieldIntoField(builder.build());
        flowModsBuilder.setFlowModSpec(caseBuilder.build());
        return flowModsBuilder.build();
    }

    private static FlowMods readFlowModCopyFromValue(ByteBuf message, short numBits) {
        FlowModCopyValueIntoFieldBuilder builder = new FlowModCopyValueIntoFieldBuilder();
        builder.setValue((int) message.readUnsignedShort());
        builder.setDstField((long) message.readInt());
        builder.setDstOfs((int) message.readShort());
        builder.setFlowModNumBits((int) numBits);
        length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;

        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
        FlowModCopyValueIntoFieldCaseBuilder caseBuilder = new FlowModCopyValueIntoFieldCaseBuilder();
        caseBuilder.setFlowModCopyValueIntoField(builder.build());
        flowModsBuilder.setFlowModSpec(caseBuilder.build());
        return flowModsBuilder.build();
    }

    private static FlowMods readFlowToPort(ByteBuf message, short numBits) {
        FlowModOutputToPortBuilder builder = new FlowModOutputToPortBuilder();
        builder.setSrcField((long) message.readInt());
        builder.setSrcOfs((int) message.readShort());
        builder.setFlowModNumBits((int) numBits);
        length -= TO_PORT_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;

        FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
        FlowModOutputToPortCaseBuilder caseBuilder = new FlowModOutputToPortCaseBuilder();
        caseBuilder.setFlowModOutputToPort(builder.build());
        flowModsBuilder.setFlowModSpec(caseBuilder.build());
        return flowModsBuilder.build();
    }

}