--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.ExtendedCommunitiesAttributeParser;
+import org.opendaylight.protocol.bgp.parser.spi.AbstractBGPExtensionProviderActivator;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.FlowspecSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.ExtendedCommunities;
+
+public final class FSActivator extends AbstractBGPExtensionProviderActivator {
+
+ private static final int FLOWSPEC_SAFI = 133;
+
+ @Override
+ protected List<AutoCloseable> startImpl(final BGPExtensionProviderContext context) {
+ final List<AutoCloseable> regs = new ArrayList<>();
+
+ regs.add(context.registerSubsequentAddressFamily(FlowspecSubsequentAddressFamily.class, FLOWSPEC_SAFI));
+
+ final ExtendedCommunitiesAttributeParser extendedCommunitiesAttributeParser = new FSExtendedCommunitiesAttributeParser(context.getReferenceCache());
+ regs.add(context.registerAttributeSerializer(ExtendedCommunities.class, extendedCommunitiesAttributeParser));
+ regs.add(context.registerAttributeParser(ExtendedCommunitiesAttributeParser.TYPE, extendedCommunitiesAttributeParser));
+
+ return regs;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, 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;
+
+import com.google.common.primitives.UnsignedBytes;
+import io.netty.buffer.ByteBuf;
+import java.util.BitSet;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
+import org.opendaylight.protocol.bgp.parser.impl.message.update.ExtendedCommunitiesAttributeParser;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.protocol.util.ReferenceCache;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.Dscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.RedirectExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.RedirectExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficActionExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficActionExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficMarkingExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficMarkingExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficRateExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficRateExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.redirect.extended.community._case.RedirectExtendedCommunity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.redirect.extended.community._case.RedirectExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.action.extended.community._case.TrafficActionExtendedCommunity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.action.extended.community._case.TrafficActionExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.marking.extended.community._case.TrafficMarkingExtendedCommunity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.marking.extended.community._case.TrafficMarkingExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.rate.extended.community._case.TrafficRateExtendedCommunity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.rate.extended.community._case.TrafficRateExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.ExtendedCommunities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.ExtendedCommunitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ShortAsNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.ExtendedCommunity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FSExtendedCommunitiesAttributeParser extends ExtendedCommunitiesAttributeParser {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FSExtendedCommunitiesAttributeParser.class);
+
+ private static final short FS_TYPE = 128;
+
+ private static final short TRAFFIC_RATE_SUBTYPE = 6;
+
+ private static final short TRAFFIC_ACTION_SUBTYPE = 7;
+
+ private static final short REDIRECT_SUBTYPE = 8;
+
+ private static final short TRAFFIC_MARKING_SUBTYPE = 9;
+
+ private static final int TRAFFIC_RATE_SIZE = 4;
+
+ private static final int RESERVED = 5;
+
+ private static final int FLAGS_SIZE = 1;
+
+ private static final int SAMPLE_BIT = 6;
+
+ private static final int TERMINAL_BIT = 7;
+
+ public FSExtendedCommunitiesAttributeParser(final ReferenceCache refCache) {
+ super(refCache);
+ }
+
+ @Override
+ public ExtendedCommunities parseExtendedCommunity(final ReferenceCache refCache, final ExtendedCommunitiesBuilder comm, final ByteBuf buffer) throws BGPDocumentedException {
+ ExtendedCommunity c = null;
+ if (comm.getCommType().equals(FS_TYPE)) {
+ switch (comm.getCommSubType()) {
+ case TRAFFIC_RATE_SUBTYPE:
+ final ShortAsNumber as = new ShortAsNumber((long) buffer.readUnsignedShort());
+ final Bandwidth value = new Bandwidth(ByteArray.readBytes(buffer, TRAFFIC_RATE_SIZE));
+ c = new TrafficRateExtendedCommunityCaseBuilder().setTrafficRateExtendedCommunity(new TrafficRateExtendedCommunityBuilder().setInformativeAs(as).setLocalAdministrator(value).build()).build();
+ break;
+ case TRAFFIC_ACTION_SUBTYPE:
+ buffer.skipBytes(RESERVED);
+ final BitSet flags = ByteArray.bytesToBitSet(ByteArray.readBytes(buffer, FLAGS_SIZE));
+ final boolean sample = flags.get(SAMPLE_BIT);
+ final boolean terminal = flags.get(TERMINAL_BIT);
+ c = new TrafficActionExtendedCommunityCaseBuilder().setTrafficActionExtendedCommunity(new TrafficActionExtendedCommunityBuilder().setSample(sample).setTerminalAction(terminal).build()).build();
+ break;
+ case REDIRECT_SUBTYPE:
+ final ShortAsNumber as1 = new ShortAsNumber((long) buffer.readUnsignedShort());
+ final byte[] byteValue = ByteArray.readBytes(buffer, TRAFFIC_RATE_SIZE);
+ c = new RedirectExtendedCommunityCaseBuilder().setRedirectExtendedCommunity(new RedirectExtendedCommunityBuilder().setGlobalAdministrator(as1).setLocalAdministrator(byteValue).build()).build();
+ break;
+ case TRAFFIC_MARKING_SUBTYPE:
+ buffer.skipBytes(RESERVED);
+ final Dscp dscp = new Dscp((short) UnsignedBytes.toInt(buffer.readByte()));
+ c = new TrafficMarkingExtendedCommunityCaseBuilder().setTrafficMarkingExtendedCommunity(new TrafficMarkingExtendedCommunityBuilder().setGlobalAdministrator(dscp).build()).build();
+ break;
+ default:
+ throw new BGPDocumentedException("Could not parse Flowspec Extended Community type: " + comm.getCommSubType(), BGPError.OPT_ATTR_ERROR);
+ }
+ }
+ if (c == null) {
+ LOG.debug("Extended community is not from Flowspec, fallback to original communities.");
+ return super.parseExtendedCommunity(refCache, comm, buffer);
+ }
+ return comm.setExtendedCommunity(c).build();
+ }
+
+ @Override
+ public void serializeExtendedCommunity(final ExtendedCommunities exCommunities, final ByteBuf buffer) {
+ final ExtendedCommunity ex = exCommunities.getExtendedCommunity();
+ if (ex instanceof TrafficRateExtendedCommunityCase) {
+ final TrafficRateExtendedCommunity trafficRate = ((TrafficRateExtendedCommunityCase) ex).getTrafficRateExtendedCommunity();
+ ByteBufWriteUtil.writeShort(trafficRate.getInformativeAs().getValue().shortValue(), buffer);
+ buffer.writeBytes(trafficRate.getLocalAdministrator().getValue());
+ }
+ else if (ex instanceof TrafficActionExtendedCommunityCase) {
+ final TrafficActionExtendedCommunity trafficAction = ((TrafficActionExtendedCommunityCase) ex).getTrafficActionExtendedCommunity();
+ buffer.writeZero(RESERVED);
+ final BitSet flags = new BitSet(FLAGS_SIZE);
+ if (trafficAction.isSample() != null) {
+ flags.set(SAMPLE_BIT, trafficAction.isSample());
+ }
+ if (trafficAction.isTerminalAction() != null) {
+ flags.set(TERMINAL_BIT, trafficAction.isTerminalAction());
+ }
+ ByteBufWriteUtil.writeBitSet(flags, FLAGS_SIZE, buffer);
+ }
+ else if (ex instanceof RedirectExtendedCommunityCase) {
+ final RedirectExtendedCommunity redirect = ((RedirectExtendedCommunityCase) ex).getRedirectExtendedCommunity();
+ ByteBufWriteUtil.writeUnsignedShort(redirect.getGlobalAdministrator().getValue().intValue(), buffer);
+ buffer.writeBytes(redirect.getLocalAdministrator());
+ }
+ else if (ex instanceof TrafficMarkingExtendedCommunityCase) {
+ final TrafficMarkingExtendedCommunity trafficMarking = ((TrafficMarkingExtendedCommunityCase) ex).getTrafficMarkingExtendedCommunity();
+ buffer.writeZero(RESERVED);
+ ByteBufWriteUtil.writeUnsignedByte(trafficMarking.getGlobalAdministrator().getValue().shortValue(), buffer);
+ } else {
+ super.serializeExtendedCommunity(exCommunities, buffer);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, 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;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.util.NoopReferenceCache;
+import org.opendaylight.protocol.util.ReferenceCache;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.Dscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.RedirectExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.RedirectExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficActionExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficActionExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficMarkingExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficMarkingExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficRateExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.TrafficRateExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.redirect.extended.community._case.RedirectExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.action.extended.community._case.TrafficActionExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.marking.extended.community._case.TrafficMarkingExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.path.attributes.extended.communities.extended.community.traffic.rate.extended.community._case.TrafficRateExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.ExtendedCommunities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ShortAsNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
+
+public class FSExtendedCommunitiesAttributeParserTest {
+
+ private final ReferenceCache ref = NoopReferenceCache.getInstance();
+
+ private static final byte[] communitiesBytes = { (byte)128, 6, 0, 72, 0, 1, 2, 3,
+ (byte)128, 7, 0, 0, 0, 0, 0, 3,
+ (byte)128, 8, 0, 35, 4, 2, 8, 7,
+ (byte)128, 9, 0, 0, 0, 0, 0, 63 };
+
+ @Test
+ public void testExtendedCommunitiesParser() {
+ final FSExtendedCommunitiesAttributeParser parser = new FSExtendedCommunitiesAttributeParser(this.ref);
+ final PathAttributesBuilder pa = new PathAttributesBuilder();
+ try {
+ parser.parseAttribute(Unpooled.copiedBuffer(communitiesBytes), pa);
+ } catch (final BGPDocumentedException e1) {
+ fail("Not expected exception: " + e1);
+ }
+
+ final TrafficRateExtendedCommunityCase expected = new TrafficRateExtendedCommunityCaseBuilder().setTrafficRateExtendedCommunity(
+ new TrafficRateExtendedCommunityBuilder().setInformativeAs(new ShortAsNumber(72L))
+ .setLocalAdministrator(new Bandwidth(new byte[] { 0, 1, 2, 3 })).build()).build();
+ ExtendedCommunities ex = pa.getExtendedCommunities().get(0);
+ final TrafficRateExtendedCommunityCase result = (TrafficRateExtendedCommunityCase) ex.getExtendedCommunity();
+ assertEquals(expected.getTrafficRateExtendedCommunity().getInformativeAs(), result.getTrafficRateExtendedCommunity().getInformativeAs());
+ assertArrayEquals(expected.getTrafficRateExtendedCommunity().getLocalAdministrator().getValue(),
+ result.getTrafficRateExtendedCommunity().getLocalAdministrator().getValue());
+
+ final TrafficActionExtendedCommunityCase expected1 = new TrafficActionExtendedCommunityCaseBuilder().setTrafficActionExtendedCommunity(
+ new TrafficActionExtendedCommunityBuilder().setSample(true).setTerminalAction(true).build()).build();
+ ex = pa.getExtendedCommunities().get(1);
+ final TrafficActionExtendedCommunityCase result1 = (TrafficActionExtendedCommunityCase) ex.getExtendedCommunity();
+ assertEquals(expected1.getTrafficActionExtendedCommunity().isSample(), result1.getTrafficActionExtendedCommunity().isSample());
+ assertEquals(expected1.getTrafficActionExtendedCommunity().isTerminalAction(), result1.getTrafficActionExtendedCommunity().isTerminalAction());
+
+ final RedirectExtendedCommunityCase expected2 = new RedirectExtendedCommunityCaseBuilder().setRedirectExtendedCommunity(
+ new RedirectExtendedCommunityBuilder().setGlobalAdministrator(new ShortAsNumber(35L)).setLocalAdministrator(
+ new byte[] { 4, 2, 8, 7 }).build()).build();
+ ex = pa.getExtendedCommunities().get(2);
+ final RedirectExtendedCommunityCase result2 = (RedirectExtendedCommunityCase) ex.getExtendedCommunity();
+ assertEquals(expected2.getRedirectExtendedCommunity().getGlobalAdministrator(),
+ result2.getRedirectExtendedCommunity().getGlobalAdministrator());
+ assertArrayEquals(expected2.getRedirectExtendedCommunity().getLocalAdministrator(),
+ result2.getRedirectExtendedCommunity().getLocalAdministrator());
+
+ final TrafficMarkingExtendedCommunityCase expected3 = new TrafficMarkingExtendedCommunityCaseBuilder().setTrafficMarkingExtendedCommunity(
+ new TrafficMarkingExtendedCommunityBuilder().setGlobalAdministrator(new Dscp((short) 63)).build()).build();
+ ex = pa.getExtendedCommunities().get(3);
+ final TrafficMarkingExtendedCommunityCase result3 = (TrafficMarkingExtendedCommunityCase) ex.getExtendedCommunity();
+ assertEquals(expected3.getTrafficMarkingExtendedCommunity().getGlobalAdministrator(),
+ result3.getTrafficMarkingExtendedCommunity().getGlobalAdministrator());
+
+ final ByteBuf serializedBuffer = Unpooled.buffer();
+ parser.serializeAttribute(pa.build(), serializedBuffer);
+ assertArrayEquals(new byte[]{ (byte)192, 16, 8, (byte)128, 6, 0, 72, 0, 1, 2, 3,
+ (byte)192, 16, 8, (byte)128, 7, 0, 0, 0, 0, 0, 3,
+ (byte)192, 16, 8, (byte)128, 8, 0, 35, 4, 2, 8, 7,
+ (byte)192, 16, 8, (byte)128, 9, 0, 0, 0, 0, 0, 63 }, ByteArray.readAllBytes(serializedBuffer));
+
+ try {
+ parser.parseAttribute(Unpooled.copiedBuffer(new byte[] { 11, 11, 21, 45, 5, 4, 3, 1 }), pa);
+ fail("Exception should have occured.");
+ } catch (final BGPDocumentedException e) {
+ assertEquals("Could not parse Extended Community type: 11", e.getMessage());
+ }
+ }
+}
<modules>
<module>concepts</module>
<module>linkstate</module>
+ <module>flowspec</module>
<module>parser-api</module>
<module>parser-spi</module>
<module>parser-impl</module>