2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowjava.nx.codec.match;
10 import com.google.common.base.MoreObjects;
11 import com.google.common.primitives.Ints;
12 import java.math.BigInteger;
13 import java.util.Objects;
14 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
15 import org.opendaylight.yangtools.yang.common.Uint64;
22 public class NxmHeader {
24 // Full 4 or 8 byte header as big integer
25 private final Uint64 header;
26 // Full 4 or 8 byte header as long
27 private final long headerAsLong;
28 // 4 byte class, field, length as long
29 private final long shortHeader;
30 private final int oxmClass;
31 private final int nxmField;
32 private final boolean hasMask;
33 private final int length;
34 private final long experimenterId;
37 * Builds a {@code NxmHeader} from a {@code BigInteger} representation,
38 * that is, one for which {@link BigInteger#longValue()} produces
39 * a valid long representation.
41 * @param header the header as {@code BigInteger}.
42 * @see NxmHeader#NxmHeader(long)
44 public NxmHeader(Uint64 header) {
45 this.headerAsLong = header.longValue();
46 if (isExperimenter(header)) {
47 this.experimenterId = (int) this.headerAsLong;
48 this.shortHeader = this.headerAsLong >>> 32;
50 this.shortHeader = this.headerAsLong;
51 this.experimenterId = -1;
55 this.oxmClass = Ints.checkedCast(extractSub(this.shortHeader, 16, 16));
56 this.nxmField = Ints.checkedCast(extractSub(this.shortHeader, 7, 9));
57 this.hasMask = extractSub(this.shortHeader, 1, 8) == 1;
58 this.length = Ints.checkedCast(extractSub(this.shortHeader, 8, 0));
62 * Builds a {@code NxmHeader} from a {@code long} representation.
63 * For non experimenter, the 4 byte header are the least
64 * significant of the long, being the other 4 most significant
65 * bytes 0. For experimenter, the full 8 byte constitute the header,
66 * being the 4 least significant the experimenter id.
68 * @param header the header as a {@code long}.
70 public NxmHeader(long header) {
71 this(Uint64.fromLongBits(header));
75 * Build a non experimenter header from it's constituent fields.
77 * @param oxmClass the OXM class.
78 * @param nxmField the NXM field.
79 * @param hasMask the hasMask field.
80 * @param length the length field.
82 public NxmHeader(int oxmClass, int nxmField, boolean hasMask, int length) {
83 this(oxmClass, nxmField, hasMask, length, -1);
87 * Build a experimenter header from it's constituent fields.
88 * The OXM class will be set to 0xFFFF.
90 * @param nxmField the NXM field.
91 * @param hasMask the hasMask field.
92 * @param length the length field.
93 * @param experimenterId the esperimenter id field.
95 public NxmHeader(int nxmField, boolean hasMask, int length, long experimenterId) {
96 this(EncodeConstants.EXPERIMENTER_VALUE, nxmField, hasMask, length, experimenterId);
99 private NxmHeader(int oxmClass, int nxmField, boolean hasMask, int length, long experimenterId) {
100 this.oxmClass = oxmClass;
101 this.nxmField = nxmField;
102 this.hasMask = hasMask;
103 this.length = length;
104 this.shortHeader = (long) oxmClass << 16 | nxmField << 9 | (hasMask ? 1 : 0) << 8 | length;
105 this.experimenterId = experimenterId;
106 if (isExperimenter()) {
107 this.header = Uint64.fromLongBits((this.shortHeader << 32) + experimenterId);
109 this.header = Uint64.valueOf(this.shortHeader);
111 this.headerAsLong = this.header.longValue();
114 private static long extractSub(final long value, final int nrBits, final int offset) {
115 final long rightShifted = value >>> offset;
116 final long mask = (1L << nrBits) - 1L;
117 return rightShifted & mask;
121 * Returns the {@code Uint64} representation of the header.
123 * @return the header.
124 * @see NxmHeader#NxmHeader(Uint64)
126 public Uint64 toUint64() {
131 * Returns the {@code long} representation of the header.
133 * @return the header.
134 * @see NxmHeader#NxmHeader(long)
136 public long toLong() {
140 public int getOxmClass() {
144 public int getNxmField() {
148 public boolean isHasMask() {
152 public int getLength() {
156 public long getExperimenterId() {
157 return experimenterId;
160 public boolean isExperimenter() {
161 return oxmClass == EncodeConstants.EXPERIMENTER_VALUE;
164 public static boolean isExperimenter(Uint64 uint) {
165 return uint.longValue() >>> 48 == EncodeConstants.EXPERIMENTER_VALUE;
169 public int hashCode() {
170 return Objects.hash(shortHeader, experimenterId);
174 public boolean equals(Object obj) {
181 if (getClass() != obj.getClass()) {
184 NxmHeader other = (NxmHeader) obj;
185 return shortHeader == other.shortHeader
186 && experimenterId == other.experimenterId;
190 public String toString() {
191 return MoreObjects.toStringHelper(this)
192 .add("header", header)
193 .add("headerAsLong", headerAsLong)
194 .add("shortHeader", shortHeader)
195 .add("oxmClass", oxmClass)
196 .add("oxmField", nxmField)
197 .add("hasMask", hasMask)
198 .add("length", length)
199 .add("experimenterId", experimenterId)