All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.openflowjava.nx.codec.match.NxmHeader Maven / Gradle / Ivy

There is a newer version: 0.19.0
Show newest version
/*
 * Copyright (c) 2014 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.openflowjava.nx.codec.match;

import com.google.common.base.MoreObjects;
import java.math.BigInteger;
import java.util.Objects;
import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
import org.opendaylight.yangtools.yang.common.Uint64;

/**
 * Nxm header.
 *
 * @author msunal
 */
public final class NxmHeader {

    // Full 4 or 8 byte header as big integer
    private final Uint64 header;
    // Full 4 or 8 byte header as long
    private final long headerAsLong;
    // 4 byte class, field, length as long
    private final long shortHeader;
    private final int oxmClass;
    private final int nxmField;
    private final boolean hasMask;
    private final int length;
    private final long experimenterId;

    /**
     * Builds a {@code NxmHeader} from a {@code BigInteger} representation,
     * that is, one for which {@link BigInteger#longValue()} produces
     * a valid long representation.
     *
     * @param header the header as {@code BigInteger}.
     * @see NxmHeader#NxmHeader(long)
     */
    public NxmHeader(final Uint64 header) {
        headerAsLong = header.longValue();
        if (isExperimenter(header)) {
            experimenterId = (int) headerAsLong;
            shortHeader = headerAsLong >>> 32;
        } else {
            shortHeader = headerAsLong;
            experimenterId = -1;
        }

        this.header = header;
        try {
            oxmClass = Math.toIntExact(extractSub(shortHeader, 16, 16));
            nxmField = Math.toIntExact(extractSub(shortHeader, 7, 9));
            hasMask = extractSub(shortHeader, 1, 8) == 1;
            length = Math.toIntExact(extractSub(shortHeader, 8, 0));
        } catch (ArithmeticException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Builds a {@code NxmHeader} from a {@code long} representation.
     * For non experimenter, the 4 byte header are the least
     * significant of the long, being the other 4 most significant
     * bytes 0. For experimenter, the full 8 byte constitute the header,
     * being the 4 least significant the experimenter id.
     *
     * @param header the header as a {@code long}.
     */
    public NxmHeader(final long header) {
        this(Uint64.fromLongBits(header));
    }

    /**
     * Build a non experimenter header from it's constituent fields.
     *
     * @param oxmClass the OXM class.
     * @param nxmField the NXM field.
     * @param hasMask the hasMask field.
     * @param length the length field.
     */
    public NxmHeader(final int oxmClass, final int nxmField, final boolean hasMask, final int length) {
        this(oxmClass, nxmField, hasMask, length, -1);
    }

    /**
     * Build a experimenter header from it's constituent fields.
     * The OXM class will be set to 0xFFFF.
     *
     * @param nxmField the NXM field.
     * @param hasMask the hasMask field.
     * @param length the length field.
     * @param experimenterId the esperimenter id field.
     */
    public NxmHeader(final int nxmField, final boolean hasMask, final int length, final long experimenterId) {
        this(EncodeConstants.EXPERIMENTER_VALUE, nxmField, hasMask, length, experimenterId);
    }

    private NxmHeader(final int oxmClass, final int nxmField, final boolean hasMask, final int length,
            final long experimenterId) {
        this.oxmClass = oxmClass;
        this.nxmField = nxmField;
        this.hasMask = hasMask;
        this.length = length;
        shortHeader = (long) oxmClass << 16 | nxmField << 9 | (hasMask ? 1 : 0) << 8 | length;
        this.experimenterId = experimenterId;
        if (isExperimenter()) {
            header = Uint64.fromLongBits((shortHeader << 32) + experimenterId);
        } else {
            header = Uint64.valueOf(shortHeader);
        }
        headerAsLong = header.longValue();
    }

    private static long extractSub(final long value, final int nrBits, final int offset) {
        final long rightShifted = value >>> offset;
        final long mask = (1L << nrBits) - 1L;
        return rightShifted & mask;
    }

    /**
     * Returns the {@code Uint64} representation of the header.
     *
     * @return the header.
     * @see NxmHeader#NxmHeader(Uint64)
     */
    public Uint64 toUint64() {
        return header;
    }

    /**
     * Returns the {@code long} representation of the header.
     *
     * @return the header.
     * @see NxmHeader#NxmHeader(long)
     */
    public long toLong() {
        return headerAsLong;
    }

    public int getOxmClass() {
        return oxmClass;
    }

    public int getNxmField() {
        return nxmField;
    }

    public boolean isHasMask() {
        return hasMask;
    }

    public int getLength() {
        return length;
    }

    public long getExperimenterId() {
        return experimenterId;
    }

    public boolean isExperimenter() {
        return oxmClass == EncodeConstants.EXPERIMENTER_VALUE;
    }

    public static boolean isExperimenter(final Uint64 uint) {
        return uint.longValue() >>> 48 == EncodeConstants.EXPERIMENTER_VALUE;
    }

    @Override
    public int hashCode() {
        return Objects.hash(shortHeader, experimenterId);
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        NxmHeader other = (NxmHeader) obj;
        return shortHeader == other.shortHeader
                && experimenterId == other.experimenterId;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("header", header)
                .add("headerAsLong", headerAsLong)
                .add("shortHeader", shortHeader)
                .add("oxmClass", oxmClass)
                .add("oxmField", nxmField)
                .add("hasMask", hasMask)
                .add("length", length)
                .add("experimenterId", experimenterId)
                .toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy