2 * Copyright (c) 2015 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.protocol.bgp.flowspec;
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Preconditions;
12 import com.google.common.primitives.UnsignedBytes;
13 import com.google.common.primitives.UnsignedInts;
14 import io.netty.buffer.ByteBuf;
15 import io.netty.buffer.Unpooled;
16 import java.util.ArrayList;
17 import java.util.List;
18 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
19 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
20 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
21 import org.opendaylight.protocol.util.BitArray;
22 import org.opendaylight.protocol.util.ByteArray;
23 import org.opendaylight.protocol.util.ByteBufWriteUtil;
24 import org.opendaylight.protocol.util.Ipv4Util;
25 import org.opendaylight.protocol.util.Values;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.BitmaskOperand;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.ComponentType;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.NumericOneByteValue;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.NumericOperand;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.NumericTwoByteValue;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.Flowspec;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.FlowspecBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.FlowspecType;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DestinationPortCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DestinationPortCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DestinationPrefixCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DestinationPrefixCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DscpCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DscpCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.FragmentCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.FragmentCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.IcmpCodeCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.IcmpCodeCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.IcmpTypeCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.IcmpTypeCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.PacketLengthCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.PacketLengthCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.PortCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.PortCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.ProtocolIpCase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.ProtocolIpCaseBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.SourcePortCase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.SourcePortCaseBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.SourcePrefixCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.SourcePrefixCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.TcpFlagsCase;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.TcpFlagsCaseBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.destination.port._case.DestinationPorts;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.destination.port._case.DestinationPortsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.dscp._case.Dscps;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.dscp._case.DscpsBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.fragment._case.Fragments;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.fragment._case.FragmentsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.icmp.code._case.Codes;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.icmp.code._case.CodesBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.icmp.type._case.Types;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.icmp.type._case.TypesBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.packet.length._case.PacketLengths;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.packet.length._case.PacketLengthsBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.port._case.Ports;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.port._case.PortsBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.protocol.ip._case.ProtocolIps;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.protocol.ip._case.ProtocolIpsBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.source.port._case.SourcePorts;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.source.port._case.SourcePortsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlags;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlagsBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCase;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCaseBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlri;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlriBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.reach.nlri.AdvertizedRoutes;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
90 import org.opendaylight.yangtools.yang.binding.DataObject;
91 import org.slf4j.Logger;
92 import org.slf4j.LoggerFactory;
94 public class FSNlriParser implements NlriParser, NlriSerializer {
95 private static final Logger LOG = LoggerFactory.getLogger(FSNlriParser.class);
97 private static final int NLRI_LENGTH = 1;
98 private static final int NLRI_LENGTH_EXTENDED = 2;
100 * Add this constant to length value to achieve all ones in the leftmost nibble.
102 private static final int LENGTH_MAGIC = 61440;
104 private static final int OPERAND_LENGTH = 8;
106 private static final int END_OF_LIST = 0;
107 private static final int AND_BIT = 1;
108 private static final int LENGTH_BITMASK = 48;
109 private static final int LENGTH_SHIFT = 4;
110 private static final int LESS_THAN = 5;
111 private static final int GREATER_THAN = 6;
112 private static final int EQUAL = 7;
114 private static final int NOT = 6;
115 private static final int MATCH = 7;
117 private static final int LAST_FRAGMENT = 4;
118 private static final int FIRST_FRAGMENT = 5;
119 private static final int IS_A_FRAGMENT = 6;
120 private static final int DONT_FRAGMENT = 7;
122 private static final int MAX_NLRI_LENGTH = 4095;
123 private static final int MAX_NLRI_LENGTH_ONE_BYTE = 240;
126 public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
127 Preconditions.checkArgument(attribute instanceof PathAttributes, "Attribute parameter is not a PathAttribute object.");
128 final PathAttributes pathAttributes = (PathAttributes) attribute;
129 final PathAttributes1 pathAttributes1 = pathAttributes.getAugmentation(PathAttributes1.class);
130 final PathAttributes2 pathAttributes2 = pathAttributes.getAugmentation(PathAttributes2.class);
131 if (pathAttributes1 != null) {
132 final AdvertizedRoutes routes = (pathAttributes1.getMpReachNlri()).getAdvertizedRoutes();
133 if (routes != null &&
134 routes.getDestinationType()
136 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCase) {
137 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCase
138 flowspecCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCase) routes.getDestinationType();
139 serializeNlri(flowspecCase.getDestinationFlowspec().getFlowspec(), byteAggregator);
141 } else if (pathAttributes2 != null) {
142 final MpUnreachNlri mpUnreachNlri = pathAttributes2.getMpUnreachNlri();
143 if (mpUnreachNlri.getWithdrawnRoutes() != null && mpUnreachNlri.getWithdrawnRoutes().getDestinationType() instanceof DestinationFlowspecCase) {
144 final DestinationFlowspecCase flowspecCase = (DestinationFlowspecCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
145 serializeNlri(flowspecCase.getDestinationFlowspec().getFlowspec(), byteAggregator);
151 * Serializes Flowspec component type that has maximum of 2B sized value field and numeric operand.
153 * @param list of items to be serialized
154 * @param nlriByteBuf where the items will be serialized
156 private static <T extends NumericTwoByteValue> void serializeNumericTwoByteValue(final List<T> list, final ByteBuf nlriByteBuf) {
157 for (final T item : list) {
158 final ByteBuf protoBuf = Unpooled.buffer();
159 writeShortest(item.getValue(), protoBuf);
160 serializeNumericOperand(item.getOp(), protoBuf.readableBytes(), nlriByteBuf);
161 nlriByteBuf.writeBytes(protoBuf);
166 * Serializes Flowspec component type that has maximum of 1B sized value field and numeric operand.
168 * @param list of items to be serialized
169 * @param nlriByteBuf where the items will be serialized
171 private static <T extends NumericOneByteValue> void serializeNumericOneByteValue(final List<T> list, final ByteBuf nlriByteBuf) {
172 for (final T type : list) {
173 serializeNumericOperand(type.getOp(), 1, nlriByteBuf);
174 writeShortest(type.getValue(), nlriByteBuf);
179 * Serializes Flowspec NLRI to ByteBuf.
181 * @param flow flowspec NLRI to be serialized
183 public static void serializeNlri(final List<Flowspec> flows, final ByteBuf buffer) {
184 final ByteBuf nlriByteBuf = Unpooled.buffer();
185 for (final Flowspec flow : flows) {
186 nlriByteBuf.writeByte(flow.getComponentType().getIntValue());
187 final FlowspecType value = flow.getFlowspecType();
188 switch (flow.getComponentType()) {
189 case DestinationPrefix:
190 nlriByteBuf.writeBytes(Ipv4Util.bytesForPrefixBegin(((DestinationPrefixCase)value).getDestinationPrefix()));
193 nlriByteBuf.writeBytes(Ipv4Util.bytesForPrefixBegin(((SourcePrefixCase)value).getSourcePrefix()));
196 serializeNumericTwoByteValue(((ProtocolIpCase)value).getProtocolIps(), nlriByteBuf);
199 serializeNumericTwoByteValue(((PortCase)value).getPorts(), nlriByteBuf);
201 case DestinationPort:
202 serializeNumericTwoByteValue(((DestinationPortCase)value).getDestinationPorts(), nlriByteBuf);
205 serializeNumericTwoByteValue(((SourcePortCase)value).getSourcePorts(), nlriByteBuf);
208 serializeNumericOneByteValue(((IcmpTypeCase)value).getTypes(), nlriByteBuf);
211 serializeNumericOneByteValue(((IcmpCodeCase)value).getCodes(), nlriByteBuf);
214 final List<TcpFlags> flags = ((TcpFlagsCase)value).getTcpFlags();
215 for (final TcpFlags flag : flags) {
216 final ByteBuf flagsBuf = Unpooled.buffer();
217 writeShortest(flag.getValue(), flagsBuf);
218 serializeBitmaskOperand(flag.getOp(), flagsBuf.readableBytes(), nlriByteBuf);
219 nlriByteBuf.writeBytes(flagsBuf);
223 serializeNumericTwoByteValue(((PacketLengthCase)value).getPacketLengths(), nlriByteBuf);
226 final List<Dscps> dscps = ((DscpCase)value).getDscps();
227 for (final Dscps dscp : dscps) {
228 serializeNumericOperand(dscp.getOp(), 1, nlriByteBuf);
229 writeShortest(dscp.getValue().getValue(), nlriByteBuf);
233 final List<Fragments> fragments = ((FragmentCase)value).getFragments();
234 for (final Fragments fragment : fragments) {
235 serializeBitmaskOperand(fragment.getOp(), 1, nlriByteBuf);
236 nlriByteBuf.writeByte(serializeFragment(fragment.getValue()));
240 LOG.warn("Unknown Component Type.");
244 Preconditions.checkState(nlriByteBuf.readableBytes() <= MAX_NLRI_LENGTH, "Maximum length of Flowspec NLRI reached.");
245 if (nlriByteBuf.readableBytes() <= MAX_NLRI_LENGTH_ONE_BYTE) {
246 buffer.writeByte(nlriByteBuf.readableBytes());
248 buffer.writeShort(nlriByteBuf.readableBytes() + LENGTH_MAGIC);
250 buffer.writeBytes(nlriByteBuf);
254 * Given the integer values, this method instead of writing the value
255 * in 4B field, compresses the value to lowest required byte field
256 * depending on the value.
258 * @param value integer to be written
259 * @param buffer ByteBuf where the value will be written
261 private static void writeShortest(final int value, final ByteBuf buffer) {
262 if (value <= Values.UNSIGNED_BYTE_MAX_VALUE) {
263 buffer.writeByte(UnsignedBytes.checkedCast(value));
264 } else if (value <= Values.UNSIGNED_SHORT_MAX_VALUE) {
265 ByteBufWriteUtil.writeUnsignedShort(value, buffer);
266 } else if (value <= Values.UNSIGNED_INT_MAX_VALUE) {
267 ByteBufWriteUtil.writeUnsignedInt(UnsignedInts.toLong(value), buffer);
269 buffer.writeLong(value);
273 private static void serializeNumericOperand(final NumericOperand op, final int length, final ByteBuf buffer) {
274 final BitArray bs = new BitArray(OPERAND_LENGTH);
275 bs.set(END_OF_LIST, op.isEndOfList());
276 bs.set(AND_BIT, op.isAndBit());
277 bs.set(LESS_THAN, op.isLessThan());
278 bs.set(GREATER_THAN, op.isGreaterThan());
279 bs.set(EQUAL, op.isEquals());
280 final byte len = (byte) (Integer.numberOfTrailingZeros(length) << LENGTH_SHIFT);
281 buffer.writeByte(bs.toByte() | len);
284 private static void serializeBitmaskOperand(final BitmaskOperand op, final int length, final ByteBuf buffer) {
285 final BitArray bs = new BitArray(OPERAND_LENGTH);
286 bs.set(END_OF_LIST, op.isEndOfList());
287 bs.set(AND_BIT, op.isAndBit());
288 bs.set(MATCH, op.isMatch());
289 bs.set(NOT, op.isNot());
290 final byte len = (byte) (Integer.numberOfTrailingZeros(length) << LENGTH_SHIFT);
291 buffer.writeByte(bs.toByte() | len);
295 public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
296 if (!nlri.isReadable()) {
299 final List<Flowspec> dst = parseNlri(nlri);
301 builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
302 new DestinationFlowspecCaseBuilder().setDestinationFlowspec(
303 new DestinationFlowspecBuilder().setFlowspec(
304 dst).build()).build()).build());
308 public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder) throws BGPParsingException {
309 if (!nlri.isReadable()) {
312 final List<Flowspec> dst = parseNlri(nlri);
314 builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
315 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCaseBuilder()
316 .setDestinationFlowspec(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder().setFlowspec(dst).build()).build()).build());
319 public static List<Flowspec> parseNlri(final ByteBuf nlri) throws BGPParsingException {
320 if (!nlri.isReadable()) {
323 final List<Flowspec> fss = new ArrayList<>();
325 // length field can be one or two bytes (if needed)
326 // check the length of nlri to see how many bytes we can skip
327 final int length = nlri.readableBytes();
328 nlri.skipBytes(length > MAX_NLRI_LENGTH_ONE_BYTE ? NLRI_LENGTH_EXTENDED : NLRI_LENGTH);
330 while(nlri.isReadable()) {
331 final FlowspecBuilder builder = new FlowspecBuilder();
333 final ComponentType type = ComponentType.forValue(nlri.readUnsignedByte());
334 builder.setComponentType(type);
336 case DestinationPrefix:
337 builder.setFlowspecType(new DestinationPrefixCaseBuilder().setDestinationPrefix(Ipv4Util.prefixForByteBuf(nlri)).build());
340 builder.setFlowspecType(new SourcePrefixCaseBuilder().setSourcePrefix(Ipv4Util.prefixForByteBuf(nlri)).build());
343 builder.setFlowspecType(new ProtocolIpCaseBuilder().setProtocolIps(parseProtocolIp(nlri)).build());
346 builder.setFlowspecType(new PortCaseBuilder().setPorts(parsePort(nlri)).build());
348 case DestinationPort:
349 builder.setFlowspecType(new DestinationPortCaseBuilder().setDestinationPorts(parseDestinationPort(nlri)).build());
352 builder.setFlowspecType(new SourcePortCaseBuilder().setSourcePorts(parseSourcePort(nlri)).build());
355 builder.setFlowspecType(new IcmpTypeCaseBuilder().setTypes(parseIcmpType(nlri)).build());
358 builder.setFlowspecType(new IcmpCodeCaseBuilder().setCodes(parseIcmpCode(nlri)).build());
361 builder.setFlowspecType(new TcpFlagsCaseBuilder().setTcpFlags(parseTcpFlags(nlri)).build());
364 builder.setFlowspecType(new PacketLengthCaseBuilder().setPacketLengths(parsePacketLength(nlri)).build());
367 builder.setFlowspecType(new DscpCaseBuilder().setDscps(parseDscp(nlri)).build());
370 builder.setFlowspecType(new FragmentCaseBuilder().setFragments(parseFragment(nlri)).build());
375 fss.add(builder.build());
380 private static List<ProtocolIps> parseProtocolIp(final ByteBuf nlri) {
381 final List<ProtocolIps> ips = new ArrayList<>();
383 // we can do this as all fields will be rewritten in the cycle
384 final ProtocolIpsBuilder builder = new ProtocolIpsBuilder();
386 final byte b = nlri.readByte();
387 final NumericOperand op = parseNumeric(b);
389 final short length = parseLength(b);
390 builder.setValue(ByteArray.bytesToInt(ByteArray.readBytes(nlri, length)));
391 end = op.isEndOfList();
392 ips.add(builder.build());
397 private static List<Ports> parsePort(final ByteBuf nlri) {
398 final List<Ports> ports = new ArrayList<>();
400 // we can do this as all fields will be rewritten in the cycle
401 final PortsBuilder builder = new PortsBuilder();
403 final byte b = nlri.readByte();
404 final NumericOperand op = parseNumeric(b);
406 final short length = parseLength(b);
407 builder.setValue(ByteArray.bytesToInt(ByteArray.readBytes(nlri, length)));
408 end = op.isEndOfList();
409 ports.add(builder.build());
414 private static List<DestinationPorts> parseDestinationPort(final ByteBuf nlri) {
415 final List<DestinationPorts> ports = new ArrayList<>();
417 // we can do this as all fields will be rewritten in the cycle
418 final DestinationPortsBuilder builder = new DestinationPortsBuilder();
420 final byte b = nlri.readByte();
421 final NumericOperand op = parseNumeric(b);
423 final short length = parseLength(b);
424 builder.setValue(ByteArray.bytesToInt(ByteArray.readBytes(nlri, length)));
425 end = op.isEndOfList();
426 ports.add(builder.build());
431 private static List<SourcePorts> parseSourcePort(final ByteBuf nlri) {
432 final List<SourcePorts> ports = new ArrayList<>();
434 // we can do this as all fields will be rewritten in the cycle
435 final SourcePortsBuilder builder = new SourcePortsBuilder();
437 final byte b = nlri.readByte();
438 final NumericOperand op = parseNumeric(b);
440 final short length = parseLength(b);
441 builder.setValue(ByteArray.bytesToInt(ByteArray.readBytes(nlri, length)));
442 end = op.isEndOfList();
443 ports.add(builder.build());
448 private static List<Types> parseIcmpType(final ByteBuf nlri) {
449 final List<Types> types = new ArrayList<>();
451 // we can do this as all fields will be rewritten in the cycle
452 final TypesBuilder builder = new TypesBuilder();
454 final byte b = nlri.readByte();
455 final NumericOperand op = parseNumeric(b);
457 builder.setValue(nlri.readUnsignedByte());
458 end = op.isEndOfList();
459 types.add(builder.build());
464 private static List<Codes> parseIcmpCode(final ByteBuf nlri) {
465 final List<Codes> codes = new ArrayList<>();
467 // we can do this as all fields will be rewritten in the cycle
468 final CodesBuilder builder = new CodesBuilder();
470 final byte b = nlri.readByte();
471 final NumericOperand op = parseNumeric(b);
473 builder.setValue(nlri.readUnsignedByte());
474 end = op.isEndOfList();
475 codes.add(builder.build());
480 private static List<TcpFlags> parseTcpFlags(final ByteBuf nlri) {
481 final List<TcpFlags> flags = new ArrayList<>();
483 // we can do this as all fields will be rewritten in the cycle
484 final TcpFlagsBuilder builder = new TcpFlagsBuilder();
486 final byte b = nlri.readByte();
487 final BitmaskOperand op = parseBitmask(b);
489 final short length = parseLength(b);
490 builder.setValue(ByteArray.bytesToInt(ByteArray.readBytes(nlri, length)));
491 end = op.isEndOfList();
492 flags.add(builder.build());
497 private static List<PacketLengths> parsePacketLength(final ByteBuf nlri) {
498 final List<PacketLengths> plengths = new ArrayList<>();
500 // we can do this as all fields will be rewritten in the cycle
501 final PacketLengthsBuilder builder = new PacketLengthsBuilder();
503 final byte b = nlri.readByte();
504 // RFC does not specify which operand to use
505 final NumericOperand op = parseNumeric(b);
507 final short length = parseLength(b);
508 builder.setValue(ByteArray.bytesToInt(ByteArray.readBytes(nlri, length)));
509 end = op.isEndOfList();
510 plengths.add(builder.build());
515 private static List<Dscps> parseDscp(final ByteBuf nlri) {
516 final List<Dscps> dscps = new ArrayList<>();
518 // we can do this as all fields will be rewritten in the cycle
519 final DscpsBuilder builder = new DscpsBuilder();
521 final byte b = nlri.readByte();
522 // RFC does not specify operator
523 final NumericOperand op = parseNumeric(b);
525 builder.setValue(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.Dscp(nlri.readUnsignedByte()));
526 end = op.isEndOfList();
527 dscps.add(builder.build());
532 private static List<Fragments> parseFragment(final ByteBuf nlri) {
533 final List<Fragments> fragments = new ArrayList<>();
535 // we can do this as all fields will be rewritten in the cycle
536 final FragmentsBuilder builder = new FragmentsBuilder();
538 final byte b = nlri.readByte();
539 final BitmaskOperand op = parseBitmask(b);
541 builder.setValue(parseFragment(nlri.readByte()));
542 end = op.isEndOfList();
543 fragments.add(builder.build());
548 private static NumericOperand parseNumeric(final byte op) {
549 final BitArray bs = BitArray.valueOf(op);
550 return new NumericOperand(bs.get(AND_BIT), bs.get(END_OF_LIST), bs.get(EQUAL), bs.get(GREATER_THAN), bs.get(LESS_THAN));
553 private static BitmaskOperand parseBitmask(final byte op) {
554 final BitArray bs = BitArray.valueOf(op);
555 return new BitmaskOperand(bs.get(AND_BIT), bs.get(END_OF_LIST), bs.get(MATCH), bs.get(NOT));
559 public static short parseLength(final byte op) {
560 return (short) (1 << ((op & LENGTH_BITMASK) >> LENGTH_SHIFT));
563 private static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.Fragment parseFragment(final byte fragment) {
564 final BitArray bs = BitArray.valueOf(fragment);
565 return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.Fragment(bs.get(DONT_FRAGMENT), bs.get(FIRST_FRAGMENT), bs.get(IS_A_FRAGMENT), bs.get(LAST_FRAGMENT));
568 private static byte serializeFragment(final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.Fragment fragment) {
569 final BitArray bs = new BitArray(Byte.SIZE);
570 bs.set(DONT_FRAGMENT, fragment.isDoNot());
571 bs.set(FIRST_FRAGMENT, fragment.isFirst());
572 bs.set(IS_A_FRAGMENT, fragment.isIsA());
573 bs.set(LAST_FRAGMENT, fragment.isLast());