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

pcap.codec.ethernet.Vlan Maven / Gradle / Ivy

There is a newer version: 1.5.1
Show newest version
/** This code is licenced under the GPL version 2. */
package pcap.codec.ethernet;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import pcap.codec.AbstractPacket;
import pcap.codec.NetworkLayer;
import pcap.codec.Packet;
import pcap.common.annotation.Inclubating;
import pcap.common.memory.Memory;
import pcap.common.util.NamedNumber;
import pcap.common.util.Strings;
import pcap.common.util.Validate;

/**
 * @see Wikipedia
 * @author Ardika Rommy Sanjaya
 */
@Inclubating
public class Vlan extends AbstractPacket {

  private final Header header;
  private final Packet payload;
  private final Builder builder;

  private Vlan(final Builder builder) {
    this.header = new Header(builder);
    this.payloadBuffer = builder.payloadBuffer;
    if (this.payloadBuffer != null
        && this.payloadBuffer.readerIndex() < this.payloadBuffer.writerIndex()) {
      this.payload =
          NetworkLayer.valueOf(this.header.type().value()).newInstance(this.payloadBuffer);
    } else {
      this.payload = null;
    }
    this.builder = builder;
  }

  public static Vlan newPacket(final Memory buffer) {
    return new Builder().build(buffer);
  }

  @Override
  public Header header() {
    return header;
  }

  @Override
  public Packet payload() {
    return payload;
  }

  @Override
  public Builder builder() {
    return builder;
  }

  @Override
  public Memory buffer() {
    return header().buffer();
  }

  @Override
  public String toString() {
    return Strings.toStringBuilder(this)
        .add("header", header())
        .add("payload", payload() != null ? payload().getClass().getSimpleName() : "(None)")
        .toString();
  }

  public static final class Header extends AbstractPacket.Header {

    public static final int VLAN_HEADER_LENGTH = 4;

    private final PriorityCodePoint priorityCodePoint; // 3 bit
    private final byte canonicalFormatIndicator; // 1 bit
    private final short vlanIdentifier; // 12 bit
    private final NetworkLayer type;

    private final Builder builder;

    private Header(final Builder builder) {
      this.priorityCodePoint = builder.priorityCodePoint;
      this.canonicalFormatIndicator = builder.canonicalFormatIndicator;
      this.vlanIdentifier = builder.vlanIdentifier;
      this.type = builder.type;
      this.buffer = resetIndex(builder.buffer, length());
      this.builder = builder;
    }

    public PriorityCodePoint priorityCodePoint() {
      return priorityCodePoint;
    }

    public int canonicalFormatIndicator() {
      return canonicalFormatIndicator & 0x01;
    }

    public int vlanIdentifier() {
      return vlanIdentifier & 0x0FFF;
    }

    public NetworkLayer type() {
      return type;
    }

    @Override
    public NetworkLayer payloadType() {
      return type;
    }

    @Override
    public int length() {
      return Header.VLAN_HEADER_LENGTH;
    }

    @Override
    public Memory buffer() {
      if (buffer == null) {
        buffer = ALLOCATOR.allocate(length());
        buffer.writeShort(
            ((priorityCodePoint.value() << 13) & 0x07)
                | ((canonicalFormatIndicator << 14) & 0x01)
                | (vlanIdentifier & 0x0FFF));
        buffer.writeShort(type.value());
      }
      return buffer;
    }

    @Override
    public Builder builder() {
      return builder;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      Header header = (Header) o;
      return canonicalFormatIndicator == header.canonicalFormatIndicator
          && vlanIdentifier == header.vlanIdentifier
          && priorityCodePoint.equals(header.priorityCodePoint)
          && type.equals(header.type);
    }

    @Override
    public int hashCode() {
      return Objects.hash(priorityCodePoint, canonicalFormatIndicator, vlanIdentifier, type);
    }

    @Override
    public String toString() {
      return Strings.toStringBuilder(this)
          .add("priorityCodePoint", priorityCodePoint())
          .add("canonicalFormatIndicator", canonicalFormatIndicator() & 0x01)
          .add("vlanIdentifier", vlanIdentifier() & 0x0FFF)
          .add("type", type())
          .toString();
    }
  }

  public static final class Builder extends AbstractPacket.Builder {

    private PriorityCodePoint priorityCodePoint = PriorityCodePoint.BE; // 3 bit
    private byte canonicalFormatIndicator; // 1 bit
    private short vlanIdentifier; // 12 bit
    private NetworkLayer type = NetworkLayer.DOT1Q_VLAN_TAGGED_FRAMES;

    private Memory buffer;
    private Memory payloadBuffer;

    /**
     * Priority code point (PCP).
     *
     * 

A 3-bit field which refers to the IEEE 802.1p class of service and maps to the frame * priority level. Different PCP values can be used to prioritize different classes of traffic. * * @param priorityCodePoint PCP. * @return returns this {@link Builder}. */ public Builder priorityCodePoint(final PriorityCodePoint priorityCodePoint) { this.priorityCodePoint = priorityCodePoint; return this; } /** * Drop eligible indicator (DEI). * *

A 1-bit field. (formerly CFI) May be used separately or in conjunction with PCP to * indicate frames eligible to be dropped in the presence of congestion. * * @param canonicalFormatIndicator CFI. * @return returns this {@link Builder}. */ public Builder canonicalFormatIndicator(final int canonicalFormatIndicator) { this.canonicalFormatIndicator = (byte) (canonicalFormatIndicator & 0x01); return this; } /** * VLAN identifier (VID). * *

A 12-bit field specifying the VLAN to which the frame belongs. * * @param vlanIdentifier vlan identifier. * @return returns this {@link Builder}. */ public Builder vlanIdentifier(final int vlanIdentifier) { this.vlanIdentifier = (short) (vlanIdentifier & 0x0FFF); return this; } /** * Next protocol type. * *

Example: {@link NetworkLayer#ARP}. * * @param type payload type. * @return returns this {@link Builder}. */ public Builder type(final NetworkLayer type) { this.type = type; return this; } @Override public Vlan build() { if (buffer != null) { return build(buffer); } return new Vlan(this); } @Override public Vlan build(final Memory buffer) { resetIndex(buffer); short tci = buffer.readShort(); short type = buffer.readShort(); this.priorityCodePoint = PriorityCodePoint.valueOf((byte) (tci >> 13 & 0x07)); this.canonicalFormatIndicator = (byte) (tci >> 14 & 0x01); this.vlanIdentifier = (short) (tci & 0x0FFF); this.type = NetworkLayer.valueOf(type); this.buffer = buffer; this.payloadBuffer = buffer.slice(); return new Vlan(this); } @Override public Builder reset() { return reset(readerIndex, Header.VLAN_HEADER_LENGTH); } @Override public Builder reset(int offset, int length) { if (buffer != null) { Validate.notIllegalArgument(offset + length <= buffer.capacity()); Validate.notIllegalArgument(priorityCodePoint != null, ILLEGAL_HEADER_EXCEPTION); Validate.notIllegalArgument(canonicalFormatIndicator >= 0, ILLEGAL_HEADER_EXCEPTION); Validate.notIllegalArgument(vlanIdentifier >= 0, ILLEGAL_HEADER_EXCEPTION); Validate.notIllegalArgument(type != null, ILLEGAL_HEADER_EXCEPTION); int index = offset; int tci = ((priorityCodePoint.value() << 13) & 0x07) | ((canonicalFormatIndicator << 14) & 0x01) | (vlanIdentifier & 0x0FFF); buffer.setShort(index, tci); index += 2; buffer.setShort(index, type.value()); } return this; } } /** @see IEEE P802.1p */ public static final class PriorityCodePoint extends NamedNumber { public static final PriorityCodePoint BK = new PriorityCodePoint((byte) 1, "Background (priority=0)"); public static final PriorityCodePoint BE = new PriorityCodePoint((byte) 0, "Best effort (default)/(priority=1)"); public static final PriorityCodePoint EE = new PriorityCodePoint((byte) 2, "Excellent effort (priority=2)"); public static final PriorityCodePoint CA = new PriorityCodePoint((byte) 3, "Critical applications (priority=3)"); public static final PriorityCodePoint VI = new PriorityCodePoint((byte) 4, "Video, < 100 ms latency and jitter (priority=4)"); public static final PriorityCodePoint VO = new PriorityCodePoint((byte) 5, "Voice, < 10 ms latency and jitter (priority=5)"); public static final PriorityCodePoint IC = new PriorityCodePoint((byte) 6, "Internetwork control (priority=6)"); public static final PriorityCodePoint NC = new PriorityCodePoint((byte) 7, "Network control (priority=7)"); private static final Map REGISTRY = new HashMap<>(); static { REGISTRY.put(BK.value(), BK); REGISTRY.put(BE.value(), BE); REGISTRY.put(EE.value(), EE); REGISTRY.put(CA.value(), CA); REGISTRY.put(VI.value(), VI); REGISTRY.put(VO.value(), VO); REGISTRY.put(IC.value(), IC); REGISTRY.put(NC.value(), NC); } protected PriorityCodePoint(Byte value, String name) { super(value, name); } /** * Get priority code point from value. * * @param value value. * @return returns {@link PriorityCodePoint}. */ public static PriorityCodePoint valueOf(final byte value) { PriorityCodePoint priorityCodePoint = REGISTRY.get(value); if (priorityCodePoint == null) { return new PriorityCodePoint((byte) -1, "UNKONWN"); } return priorityCodePoint; } /** * Add new {@link PriorityCodePoint} to registry. * * @param priorityCodePoint priority code point. * @return returns {@link PriorityCodePoint}. */ public static PriorityCodePoint register(final PriorityCodePoint priorityCodePoint) { REGISTRY.put(priorityCodePoint.value(), priorityCodePoint); return priorityCodePoint; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy