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 java.math.BigInteger;
12 import java.util.Objects;
13 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
14 import org.opendaylight.yangtools.yang.common.Uint64;
21 public class NxmHeader {
23 // Full 4 or 8 byte header as big integer
24 private final Uint64 header;
25 // Full 4 or 8 byte header as long
26 private final long headerAsLong;
27 // 4 byte class, field, length as long
28 private final long shortHeader;
29 private final int oxmClass;
30 private final int nxmField;
31 private final boolean hasMask;
32 private final int length;
33 private final long experimenterId;
36 * Builds a {@code NxmHeader} from a {@code BigInteger} representation,
37 * that is, one for which {@link BigInteger#longValue()} produces
38 * a valid long representation.
40 * @param header the header as {@code BigInteger}.
41 * @see NxmHeader#NxmHeader(long)
43 public NxmHeader(final Uint64 header) {
44 this.headerAsLong = header.longValue();
45 if (isExperimenter(header)) {
46 this.experimenterId = (int) this.headerAsLong;
47 this.shortHeader = this.headerAsLong >>> 32;
49 this.shortHeader = this.headerAsLong;
50 this.experimenterId = -1;
55 this.oxmClass = Math.toIntExact(extractSub(this.shortHeader, 16, 16));
56 this.nxmField = Math.toIntExact(extractSub(this.shortHeader, 7, 9));
57 this.hasMask = extractSub(this.shortHeader, 1, 8) == 1;
58 this.length = Math.toIntExact(extractSub(this.shortHeader, 8, 0));
59 } catch (ArithmeticException e) {
60 throw new IllegalArgumentException(e);
65 * Builds a {@code NxmHeader} from a {@code long} representation.
66 * For non experimenter, the 4 byte header are the least
67 * significant of the long, being the other 4 most significant
68 * bytes 0. For experimenter, the full 8 byte constitute the header,
69 * being the 4 least significant the experimenter id.
71 * @param header the header as a {@code long}.
73 public NxmHeader(final long header) {
74 this(Uint64.fromLongBits(header));
78 * Build a non experimenter header from it's constituent fields.
80 * @param oxmClass the OXM class.
81 * @param nxmField the NXM field.
82 * @param hasMask the hasMask field.
83 * @param length the length field.
85 public NxmHeader(final int oxmClass, final int nxmField, final boolean hasMask, final int length) {
86 this(oxmClass, nxmField, hasMask, length, -1);
90 * Build a experimenter header from it's constituent fields.
91 * The OXM class will be set to 0xFFFF.
93 * @param nxmField the NXM field.
94 * @param hasMask the hasMask field.
95 * @param length the length field.
96 * @param experimenterId the esperimenter id field.
98 public NxmHeader(final int nxmField, final boolean hasMask, final int length, final long experimenterId) {
99 this(EncodeConstants.EXPERIMENTER_VALUE, nxmField, hasMask, length, experimenterId);
102 private NxmHeader(final int oxmClass, final int nxmField, final boolean hasMask, final int length,
103 final long experimenterId) {
104 this.oxmClass = oxmClass;
105 this.nxmField = nxmField;
106 this.hasMask = hasMask;
107 this.length = length;
108 this.shortHeader = (long) oxmClass << 16 | nxmField << 9 | (hasMask ? 1 : 0) << 8 | length;
109 this.experimenterId = experimenterId;
110 if (isExperimenter()) {
111 this.header = Uint64.fromLongBits((this.shortHeader << 32) + experimenterId);
113 this.header = Uint64.valueOf(this.shortHeader);
115 this.headerAsLong = this.header.longValue();
118 private static long extractSub(final long value, final int nrBits, final int offset) {
119 final long rightShifted = value >>> offset;
120 final long mask = (1L << nrBits) - 1L;
121 return rightShifted & mask;
125 * Returns the {@code Uint64} representation of the header.
127 * @return the header.
128 * @see NxmHeader#NxmHeader(Uint64)
130 public Uint64 toUint64() {
135 * Returns the {@code long} representation of the header.
137 * @return the header.
138 * @see NxmHeader#NxmHeader(long)
140 public long toLong() {
144 public int getOxmClass() {
148 public int getNxmField() {
152 public boolean isHasMask() {
156 public int getLength() {
160 public long getExperimenterId() {
161 return experimenterId;
164 public boolean isExperimenter() {
165 return oxmClass == EncodeConstants.EXPERIMENTER_VALUE;
168 public static boolean isExperimenter(final Uint64 uint) {
169 return uint.longValue() >>> 48 == EncodeConstants.EXPERIMENTER_VALUE;
173 public int hashCode() {
174 return Objects.hash(shortHeader, experimenterId);
178 public boolean equals(final Object obj) {
185 if (getClass() != obj.getClass()) {
188 NxmHeader other = (NxmHeader) obj;
189 return shortHeader == other.shortHeader
190 && experimenterId == other.experimenterId;
194 public String toString() {
195 return MoreObjects.toStringHelper(this)
196 .add("header", header)
197 .add("headerAsLong", headerAsLong)
198 .add("shortHeader", shortHeader)
199 .add("oxmClass", oxmClass)
200 .add("oxmField", nxmField)
201 .add("hasMask", hasMask)
202 .add("length", length)
203 .add("experimenterId", experimenterId)