import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.opendaylight.protocol.bgp.flowspec.handlers.FlowspecTypeParser;
import org.opendaylight.protocol.bgp.flowspec.handlers.FlowspecTypeSerializer;
import org.opendaylight.protocol.bgp.flowspec.handlers.NumericOneByteOperandParser;
import org.opendaylight.protocol.bgp.flowspec.handlers.Util;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.Dscp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.NumericOperand;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.FlowspecType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.DscpCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.dscp._case.DscpsBuilder;
public final class FSDscpHandler implements FlowspecTypeParser, FlowspecTypeSerializer {
- public static final int DSCP_VALUE = 11;
+ static final int DSCP_VALUE = 11;
- @Override
- public void serializeType(FlowspecType fsType, ByteBuf output) {
- Preconditions.checkArgument(fsType instanceof DscpCase, "DscpCase class is mandatory!");
- output.writeByte(DSCP_VALUE);
- serializeDscps(((DscpCase) fsType).getDscps(), output);
- }
-
- @Override
- public FlowspecType parseType(ByteBuf buffer) {
- requireNonNull(buffer, "input buffer is null, missing data to parse.");
- return new DscpCaseBuilder().setDscps(parseDscps(buffer)).build();
- }
-
- private static final void serializeDscps(final List<Dscps> dscps, final ByteBuf nlriByteBuf) {
- for (final Dscps dscp : dscps) {
- NumericOneByteOperandParser.INSTANCE.serialize(dscp.getOp(), 1, nlriByteBuf);
+ private static void serializeDscps(final List<Dscps> dscps, final ByteBuf nlriByteBuf) {
+ for (final Iterator<Dscps> it = dscps.iterator(); it.hasNext(); ) {
+ final Dscps dscp = it.next();
+ NumericOneByteOperandParser.INSTANCE.serialize(dscp.getOp(), 1, !it.hasNext(), nlriByteBuf);
Util.writeShortest(dscp.getValue().getValue(), nlriByteBuf);
}
}
// RFC does not specify operator
final NumericOperand op = NumericOneByteOperandParser.INSTANCE.parse(b);
builder.setOp(op);
- builder.setValue(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.Dscp(nlri.readUnsignedByte()));
+ builder.setValue(new Dscp(nlri.readUnsignedByte()));
end = op.isEndOfList();
dscps.add(builder.build());
}
return dscps;
}
+
+ @Override
+ public void serializeType(final FlowspecType fsType, final ByteBuf output) {
+ Preconditions.checkArgument(fsType instanceof DscpCase, "DscpCase class is mandatory!");
+ output.writeByte(DSCP_VALUE);
+ serializeDscps(((DscpCase) fsType).getDscps(), output);
+ }
+
+ @Override
+ public FlowspecType parseType(final ByteBuf buffer) {
+ requireNonNull(buffer, "input buffer is null, missing data to parse.");
+ return new DscpCaseBuilder().setDscps(parseDscps(buffer)).build();
+ }
}
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractOperandParser;
import org.opendaylight.protocol.bgp.flowspec.handlers.FlowspecTypeParser;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.group.ipv6.flowspec.flowspec.type.flow.label._case.FlowLabelBuilder;
public final class FSIpv6FlowLabelHandler implements FlowspecTypeParser, FlowspecTypeSerializer {
- public static final int FLOW_LABEL_VALUE = 13;
+ static final int FLOW_LABEL_VALUE = 13;
+
+ private static void serializeNumericFourByteValue(final List<FlowLabel> list, final ByteBuf nlriByteBuf) {
+ for (final Iterator<FlowLabel> it = list.iterator(); it.hasNext(); ) {
+ final FlowLabel label = it.next();
+ final ByteBuf protoBuf = Unpooled.buffer();
+ Util.writeShortest(label.getValue().intValue(), protoBuf);
+ NumericOneByteOperandParser.INSTANCE.serialize(label.getOp(), protoBuf.readableBytes(),
+ !it.hasNext(), nlriByteBuf);
+ nlriByteBuf.writeBytes(protoBuf);
+ }
+ }
@Override
- public void serializeType(FlowspecType fsType, ByteBuf output) {
+ public void serializeType(final FlowspecType fsType, final ByteBuf output) {
Preconditions.checkArgument(fsType instanceof FlowLabelCase, "FlowLabelCase class is mandatory!");
output.writeByte(FLOW_LABEL_VALUE);
serializeNumericFourByteValue(((FlowLabelCase) fsType).getFlowLabel(), output);
}
@Override
- public FlowspecType parseType(ByteBuf buffer) {
+ public FlowspecType parseType(final ByteBuf buffer) {
return new FlowLabelCaseBuilder().setFlowLabel(parseFlowLabel(buffer)).build();
}
- private static void serializeNumericFourByteValue(final List<FlowLabel> list, final ByteBuf nlriByteBuf) {
- for (final FlowLabel item : list) {
- final ByteBuf protoBuf = Unpooled.buffer();
- Util.writeShortest(item.getValue().intValue(), protoBuf);
- NumericOneByteOperandParser.INSTANCE.serialize(item.getOp(), protoBuf.readableBytes(), nlriByteBuf);
- nlriByteBuf.writeBytes(protoBuf);
- }
- }
-
private static List<FlowLabel> parseFlowLabel(final ByteBuf nlri) {
final List<FlowLabel> labels = new ArrayList<>();
boolean end = false;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractOperandParser;
import org.opendaylight.protocol.bgp.flowspec.handlers.BitmaskOperandParser;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlagsBuilder;
public final class FSTcpFlagsHandler implements FlowspecTypeParser, FlowspecTypeSerializer {
- public static final int TCP_FLAGS_VALUE = 9;
+ static final int TCP_FLAGS_VALUE = 9;
+
+ private static void serializeTcpFlags(final List<TcpFlags> flags, final ByteBuf nlriByteBuf) {
+ for (final Iterator<TcpFlags> it = flags.iterator(); it.hasNext(); ) {
+ final TcpFlags flag = it.next();
+ final ByteBuf flagsBuf = Unpooled.buffer();
+ Util.writeShortest(flag.getValue(), flagsBuf);
+ BitmaskOperandParser.INSTANCE.serialize(flag.getOp(), flagsBuf.readableBytes(),
+ !it.hasNext(), nlriByteBuf);
+ nlriByteBuf.writeBytes(flagsBuf);
+ }
+ }
@Override
- public void serializeType(FlowspecType fsType, ByteBuf output) {
+ public void serializeType(final FlowspecType fsType, final ByteBuf output) {
Preconditions.checkArgument(fsType instanceof TcpFlagsCase, "TcpFlagsCase class is mandatory!");
output.writeByte(TCP_FLAGS_VALUE);
serializeTcpFlags(((TcpFlagsCase) fsType).getTcpFlags(), output);
}
@Override
- public FlowspecType parseType(ByteBuf buffer) {
+ public FlowspecType parseType(final ByteBuf buffer) {
requireNonNull(buffer, "input buffer is null, missing data to parse.");
return new TcpFlagsCaseBuilder().setTcpFlags(parseTcpFlags(buffer)).build();
}
- private static final void serializeTcpFlags(final List<TcpFlags> flags, final ByteBuf nlriByteBuf) {
- for (final TcpFlags flag : flags) {
- final ByteBuf flagsBuf = Unpooled.buffer();
- Util.writeShortest(flag.getValue(), flagsBuf);
- BitmaskOperandParser.INSTANCE.serialize(flag.getOp(), flagsBuf.readableBytes(), nlriByteBuf);
- nlriByteBuf.writeBytes(flagsBuf);
- }
- }
-
private static List<TcpFlags> parseTcpFlags(final ByteBuf nlri) {
final List<TcpFlags> flags = new ArrayList<>();
boolean end = false;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.BitmaskOperand;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.Fragment;
public static final int FRAGMENT_VALUE = 12;
- protected static final int LAST_FRAGMENT = 4;
- protected static final int FIRST_FRAGMENT = 5;
- protected static final int IS_A_FRAGMENT = 6;
- protected static final int DONT_FRAGMENT = 7;
+ static final int LAST_FRAGMENT = 4;
+ static final int FIRST_FRAGMENT = 5;
+ static final int IS_A_FRAGMENT = 6;
+ static final int DONT_FRAGMENT = 7;
protected abstract Fragment parseFragment(final byte fragment);
protected abstract byte serializeFragment(final Fragment fragment);
@Override
- public void serializeType(FlowspecType fsType, ByteBuf output) {
+ public void serializeType(final FlowspecType fsType, final ByteBuf output) {
Preconditions.checkArgument(fsType instanceof FragmentCase, "FragmentCase class is mandatory!");
output.writeByte(FRAGMENT_VALUE);
serializeFragments(((FragmentCase) fsType).getFragments(), output);
}
@Override
- public FlowspecType parseType(ByteBuf buffer) {
+ public FlowspecType parseType(final ByteBuf buffer) {
if (buffer == null) {
return null;
}
return new FragmentCaseBuilder().setFragments(parseFragments(buffer)).build();
}
- protected final void serializeFragments(final List<Fragments> fragments, final ByteBuf nlriByteBuf) {
- for (final Fragments fragment : fragments) {
- BitmaskOperandParser.INSTANCE.serialize(fragment.getOp(), 1, nlriByteBuf);
+ private void serializeFragments(final List<Fragments> fragments, final ByteBuf nlriByteBuf) {
+ for (final Iterator<Fragments> it = fragments.iterator(); it.hasNext(); ) {
+ final Fragments fragment = it.next();
+ BitmaskOperandParser.INSTANCE.serialize(fragment.getOp(), 1, !it.hasNext(), nlriByteBuf);
nlriByteBuf.writeByte(serializeFragment(fragment.getValue()));
}
}
- protected final List<Fragments> parseFragments(final ByteBuf nlri) {
+ private List<Fragments> parseFragments(final ByteBuf nlri) {
final List<Fragments> fragments = new ArrayList<>();
boolean end = false;
// we can do this as all fields will be rewritten in the cycle
import io.netty.buffer.ByteBuf;
import java.util.List;
import java.util.Set;
-
import org.opendaylight.protocol.util.BitArray;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.NumericOperand;
@VisibleForTesting
public static final String LESS_THAN_VALUE = "less-than";
- protected static final int LESS_THAN = 5;
- protected static final int GREATER_THAN = 6;
- protected static final int EQUAL = 7;
+ private static final int LESS_THAN = 5;
+ private static final int GREATER_THAN = 6;
+ private static final int EQUAL = 7;
/**
* Serializes specific numeric operand type depending on the length field value.
@Override
public final NumericOperand create(final Set<String> operandValues) {
- return new NumericOperand(operandValues.contains(AND_BIT_VALUE), operandValues.contains(END_OF_LIST_VALUE), operandValues.contains(EQUALS_VALUE), operandValues.contains(GREATER_THAN_VALUE), operandValues.contains(LESS_THAN_VALUE));
+ return new NumericOperand(
+ operandValues.contains(AND_BIT_VALUE),
+ operandValues.contains(END_OF_LIST_VALUE),
+ operandValues.contains(EQUALS_VALUE),
+ operandValues.contains(GREATER_THAN_VALUE),
+ operandValues.contains(LESS_THAN_VALUE)
+ );
}
@Override
- public final void serialize(final NumericOperand operand, final int length, final ByteBuf buffer) {
+ public final void serialize(final NumericOperand operand, final int length,
+ final boolean endOfList, final ByteBuf buffer) {
final BitArray operandValues = new BitArray(OPERAND_LENGTH);
- operandValues.set(END_OF_LIST, operand.isEndOfList());
+ operandValues.set(END_OF_LIST, endOfList);
operandValues.set(AND_BIT, operand.isAndBit());
operandValues.set(LESS_THAN, operand.isLessThan());
operandValues.set(GREATER_THAN, operand.isGreaterThan());
@Override
public final NumericOperand parse(final byte operand) {
final BitArray operandValues = BitArray.valueOf(operand);
- return new NumericOperand(operandValues.get(AND_BIT), operandValues.get(END_OF_LIST), operandValues.get(EQUAL), operandValues.get(GREATER_THAN), operandValues.get(LESS_THAN));
+ return new NumericOperand(
+ operandValues.get(AND_BIT),
+ operandValues.get(END_OF_LIST),
+ operandValues.get(EQUAL),
+ operandValues.get(GREATER_THAN),
+ operandValues.get(LESS_THAN)
+ );
}
@Override
*
* @param op operand to be serialized
* @param length value of the 'length' field
+ * @param endOfList if this operand is at the end of the list
* @param buffer where the operand will be serialized to
*/
- protected abstract void serialize(final T op, final int length, final ByteBuf buffer);
+ protected abstract void serialize(final T op, final int length, final boolean endOfList,
+ final ByteBuf buffer);
/**
* Parses operand from byte value.
import com.google.common.annotations.VisibleForTesting;
import io.netty.buffer.ByteBuf;
import java.util.Set;
-
import org.opendaylight.protocol.util.BitArray;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.BitmaskOperand;
private static final int NOT = 6;
private static final int MATCH = 7;
- private BitmaskOperandParser() {
-
- }
+ private BitmaskOperandParser() { }
@Override
public BitmaskOperand create(final Set<String> opValues) {
- return new BitmaskOperand(opValues.contains(AND_BIT_VALUE), opValues.contains(END_OF_LIST_VALUE), opValues.contains(MATCH_VALUE), opValues.contains(NOT_VALUE));
+ return new BitmaskOperand(
+ opValues.contains(AND_BIT_VALUE),
+ opValues.contains(END_OF_LIST_VALUE),
+ opValues.contains(MATCH_VALUE),
+ opValues.contains(NOT_VALUE)
+ );
}
@Override
- public void serialize(final BitmaskOperand op, final int length, final ByteBuf buffer) {
+ public void serialize(final BitmaskOperand op, final int length, final boolean endOfList,
+ final ByteBuf buffer) {
final BitArray bs = new BitArray(OPERAND_LENGTH);
- bs.set(END_OF_LIST, op.isEndOfList());
+ bs.set(END_OF_LIST, endOfList);
bs.set(AND_BIT, op.isAndBit());
bs.set(MATCH, op.isMatch());
bs.set(NOT, op.isNot());
package org.opendaylight.protocol.bgp.flowspec.handlers;
import io.netty.buffer.ByteBuf;
+import java.util.Iterator;
import java.util.List;
-
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.NumericOneByteValue;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.NumericOperand;
*/
@Override
public <T extends NumericOneByteValue> void serialize(final List<T> list, final ByteBuf nlriByteBuf) {
- for (final T operand : list) {
- super.serialize(operand.getOp(), 1, nlriByteBuf);
+ for (final Iterator<T> it = list.iterator(); it.hasNext(); ) {
+ final T operand = it.next();
+ super.serialize(operand.getOp(), 1, !it.hasNext(), nlriByteBuf);
Util.writeShortest(operand.getValue(), nlriByteBuf);
}
}
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
+import java.util.Iterator;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.NumericOperand;
*/
@Override
public <T extends NumericTwoByteValue> void serialize(final List<T> list, final ByteBuf nlriByteBuf) {
- for (final T operand : list) {
+ for (final Iterator<T> it = list.iterator(); it.hasNext(); ) {
+ final T operand = it.next();
final ByteBuf protoBuf = Unpooled.buffer();
Util.writeShortest(operand.getValue(), protoBuf);
- super.serialize(operand.getOp(), protoBuf.readableBytes(), nlriByteBuf);
+ super.serialize(operand.getOp(), protoBuf.readableBytes(), !it.hasNext(), nlriByteBuf);
nlriByteBuf.writeBytes(protoBuf);
}
}
--- /dev/null
+/*
+ * Copyright (c) 2017 Lumina Networks, 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.protocol.bgp.flowspec.handlers;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.NumericOperand;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.icmp.code._case.Codes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.icmp.code._case.CodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.port._case.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.port._case.PortsBuilder;
+
+public class NumericOperandParserTest {
+ private static final byte[] ONE_BYTE_CODE_LIST = new byte[]{
+ 0x01, 0x64,
+ 0x01, 0x65,
+ (byte) 0x81, 0x66, // last port in the list should have end-of-list set
+ };
+
+ @Test
+ public void testSerializeTwoByte() {
+ final ByteBuf nlriByteBuf = Unpooled.buffer();
+ final List<Ports> ports = new ArrayList<>();
+ // create 3 ports without end-of-list bit set
+ for (int i = 0; i < 3; i++) {
+ ports.add(
+ new PortsBuilder()
+ .setOp(new NumericOperand(false, false, true, false, false))
+ .setValue(100 + i)
+ .build()
+ );
+ }
+ NumericTwoByteOperandParser.INSTANCE.serialize(ports, nlriByteBuf);
+ assertArrayEquals(ONE_BYTE_CODE_LIST, ByteArray.readAllBytes(nlriByteBuf));
+ }
+
+ @Test
+ public void testSerializeOneByte() {
+ final ByteBuf nlriByteBuf = Unpooled.buffer();
+ final List<Codes> codes = new ArrayList<>();
+ // create 3 ports without end-of-list bit set
+ for (int i = 0; i < 3; i++) {
+ codes.add(
+ new CodesBuilder()
+ .setOp(new NumericOperand(false, false, true, false, false))
+ .setValue((short) (100 + i))
+ .build()
+ );
+ }
+ NumericOneByteOperandParser.INSTANCE.serialize(codes, nlriByteBuf);
+ assertArrayEquals(ONE_BYTE_CODE_LIST, ByteArray.readAllBytes(nlriByteBuf));
+ }
+
+ @Test
+ public void testSerializeVariableByte() {
+ final ByteBuf nlriByteBuf = Unpooled.buffer();
+ // test with a operand with endOfList set to true, but override with false
+ NumericOneByteOperandParser.INSTANCE.serialize(
+ new NumericOperand(false, true, true, false, false),
+ 1,
+ false,
+ nlriByteBuf);
+ assertArrayEquals(new byte[]{(byte) 0x01}, ByteArray.readAllBytes(nlriByteBuf));
+
+ // test with a operand with endOfList set to false, but override with true
+ nlriByteBuf.clear();
+ NumericOneByteOperandParser.INSTANCE.serialize(
+ new NumericOperand(false, true, true, false, false),
+ 1,
+ true,
+ nlriByteBuf);
+ assertArrayEquals(new byte[]{(byte) 0x81}, ByteArray.readAllBytes(nlriByteBuf));
+ }
+}
\ No newline at end of file