import org.opendaylight.protocol.bgp.parser.impl.message.BGPNotificationMessageParser;
import org.opendaylight.protocol.bgp.parser.impl.message.BGPOpenMessageParser;
import org.opendaylight.protocol.bgp.parser.impl.message.BGPUpdateMessageParser;
+import org.opendaylight.protocol.bgp.parser.impl.message.open.AddPathCapabilityHandler;
import org.opendaylight.protocol.bgp.parser.impl.message.open.As4CapabilityHandler;
import org.opendaylight.protocol.bgp.parser.impl.message.open.CapabilityParameterParser;
import org.opendaylight.protocol.bgp.parser.impl.message.open.GracefulCapabilityHandler;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.OriginatorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.message.WithdrawnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.AddPathCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.GracefulRestartCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
regs.add(context.registerCapabilityParser(MultiProtocolCapabilityHandler.CODE, multi));
regs.add(context.registerCapabilitySerializer(MultiprotocolCapability.class, multi));
+ final AddPathCapabilityHandler addPath = new AddPathCapabilityHandler(afiReg, safiReg);
+ regs.add(context.registerCapabilityParser(AddPathCapabilityHandler.CODE, addPath));
+ regs.add(context.registerCapabilitySerializer(AddPathCapability.class, addPath));
+
final As4CapabilityHandler as4 = new As4CapabilityHandler();
regs.add(context.registerCapabilityParser(As4CapabilityHandler.CODE, as4));
regs.add(context.registerCapabilitySerializer(As4BytesCapability.class, as4));
--- /dev/null
+/*
+ * Copyright (c) 2016 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.parser.impl.message.open;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.CapabilityParser;
+import org.opendaylight.protocol.bgp.parser.spi.CapabilitySerializer;
+import org.opendaylight.protocol.bgp.parser.spi.CapabilityUtil;
+import org.opendaylight.protocol.bgp.parser.spi.SubsequentAddressFamilyRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.AddPathCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.AddPathCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies.SendReceive;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamiliesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
+
+public class AddPathCapabilityHandler implements CapabilityParser, CapabilitySerializer {
+
+ public static final int CODE = 69;
+ private static final int TRIPLET_BYTE_SIZE = 4;
+
+ private final AddressFamilyRegistry afiReg;
+ private final SubsequentAddressFamilyRegistry safiReg;
+
+ public AddPathCapabilityHandler(final AddressFamilyRegistry afiReg, final SubsequentAddressFamilyRegistry safiReg) {
+ this.afiReg = Preconditions.checkNotNull(afiReg);
+ this.safiReg = Preconditions.checkNotNull(safiReg);
+ }
+
+ @Override
+ public void serializeCapability(final CParameters capability, final ByteBuf byteAggregator) {
+ if ( (capability.getAugmentation(CParameters1.class) == null)
+ || (capability.getAugmentation(CParameters1.class).getAddPathCapability() == null) ) {
+ return;
+ }
+ final AddPathCapability addPathCap = capability.getAugmentation(CParameters1.class).getAddPathCapability();
+
+ final List<AddressFamilies> families = addPathCap.getAddressFamilies();
+ final ByteBuf capBuffer = Unpooled.buffer(families.size() * TRIPLET_BYTE_SIZE);
+ for (final AddressFamilies addressFamily : families) {
+ final Class<? extends AddressFamily> afi = addressFamily.getAfi();
+ final Integer afival = this.afiReg.numberForClass(afi);
+ Preconditions.checkArgument(afival != null, "Unhandled address family " + afi);
+ capBuffer.writeShort(afival);
+
+ final Class<? extends SubsequentAddressFamily> safi = addressFamily.getSafi();
+ final Integer safival = this.safiReg.numberForClass(safi);
+ Preconditions.checkArgument(safival != null, "Unhandled subsequent address family " + safi);
+ capBuffer.writeByte(safival);
+
+ final SendReceive sendReceive = addressFamily.getSendReceive();
+ Preconditions.checkArgument(sendReceive != null, "Unhandled Send/Receive value");
+ capBuffer.writeByte(sendReceive.getIntValue());
+ }
+
+ CapabilityUtil.formatCapability(CODE, capBuffer, byteAggregator);
+ }
+
+ @Override
+ public CParameters parseCapability(final ByteBuf buffer) throws BGPDocumentedException, BGPParsingException {
+ final List<AddressFamilies> families = new ArrayList<>();
+ while (buffer.isReadable()) {
+ final int afiVal = buffer.readUnsignedShort();
+ final Class<? extends AddressFamily> afi = this.afiReg.classForFamily(afiVal);
+ if (afi == null) {
+ throw new BGPParsingException("Address Family Identifier: '" + afiVal + "' not supported.");
+ }
+ final int safiVal = buffer.readUnsignedByte();
+ final Class<? extends SubsequentAddressFamily> safi = this.safiReg.classForFamily(safiVal);
+ if (safi == null) {
+ throw new BGPParsingException("Subsequent Address Family Identifier: '" + safiVal + "' not supported.");
+ }
+ final SendReceive sendReceive = SendReceive.forValue(buffer.readUnsignedByte());
+ if (sendReceive != null) {
+ families.add(new AddressFamiliesBuilder().setAfi(afi).setSafi(safi).setSendReceive(sendReceive).build());
+ }
+ }
+ return new CParametersBuilder().addAugmentation(CParameters1.class,new CParameters1Builder().setAddPathCapability(
+ new AddPathCapabilityBuilder().setAddressFamilies(families).build()).build()).build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.parser.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.impl.message.open.AddPathCapabilityHandler;
+import org.opendaylight.protocol.bgp.parser.spi.AddressFamilyRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.SubsequentAddressFamilyRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.AddPathCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamilies.SendReceive;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.add.path.capability.AddressFamiliesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv6AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
+
+public class AddPathCapabilityHandlerTest {
+ private final static Class afi = Ipv6AddressFamily.class;
+ @Mock private AddressFamilyRegistry afiRegistry;
+ @Mock private AddressFamilyRegistry afirExpection;
+ private final static Class safi = UnicastSubsequentAddressFamily.class;
+ @Mock private SubsequentAddressFamilyRegistry safiRegistry;
+ @Mock private SubsequentAddressFamilyRegistry safirException;
+ private final ByteBuf parseCorrectBytes = Unpooled.copiedBuffer(new byte[] {1, 4, 4, 1});
+ private final ByteBuf parseWrongBytes = Unpooled.copiedBuffer(new byte[] {1, 4, 4, 4});
+ private final byte[] serializedBytes = new byte[] {AddPathCapabilityHandler.CODE, 4, 1, 4, 4, 1};
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Mockito.doReturn(260).when(this.afiRegistry).numberForClass(afi);
+ Mockito.doReturn(this.afi).when(this.afiRegistry).classForFamily(260);
+
+ Mockito.doReturn(null).when(this.afirExpection).numberForClass(afi);
+ Mockito.doReturn(null).when(this.afirExpection).classForFamily(260);
+
+ Mockito.doReturn(4).when(this.safiRegistry).numberForClass(safi);
+ Mockito.doReturn(this.safi).when(this.safiRegistry).classForFamily(4);
+
+ Mockito.doReturn(null).when(this.safirException).numberForClass(safi);
+ Mockito.doReturn(null).when(this.safirException).classForFamily(4);
+ }
+
+ @Test
+ public void testCapabilityHandler() throws BGPDocumentedException, BGPParsingException {
+ final List<AddressFamilies> family = new ArrayList<AddressFamilies>();
+ family.add(new AddressFamiliesBuilder().setAfi(this.afi).setSafi(this.safi).setSendReceive(SendReceive.forValue(1)).build());
+
+ final CParameters capabilityToSerialize = new CParametersBuilder().addAugmentation(CParameters1.class, new CParameters1Builder().setAddPathCapability(
+ new AddPathCapabilityBuilder().setAddressFamilies(family).build()).build()).build();
+
+ final ByteBuf bytes = Unpooled.buffer(6);
+ final AddPathCapabilityHandler handler = new AddPathCapabilityHandler(this.afiRegistry, this.safiRegistry);
+ handler.serializeCapability(capabilityToSerialize, bytes);
+ assertArrayEquals(this.serializedBytes, bytes.array());
+
+ final CParameters newCaps = handler.parseCapability(this.parseCorrectBytes);
+ assertEquals(capabilityToSerialize.hashCode(), newCaps.hashCode());
+ }
+
+ @Test(expected=BGPParsingException.class)
+ public void testAfiException() throws BGPDocumentedException, BGPParsingException {
+ final ByteBuf bytes = this.parseWrongBytes.copy();
+ final AddPathCapabilityHandler handler = new AddPathCapabilityHandler(this.afirExpection, this.safiRegistry);
+ handler.parseCapability(bytes);
+ }
+
+ @Test(expected=BGPParsingException.class)
+ public void testSafiException() throws BGPDocumentedException, BGPParsingException {
+ final ByteBuf bytes = this.parseWrongBytes.copy();
+ final AddPathCapabilityHandler handler = new AddPathCapabilityHandler(this.afiRegistry, this.safirException);
+ handler.parseCapability(bytes);
+ }
+
+ @Test
+ public void testSendReceiveIgnored() throws BGPDocumentedException, BGPParsingException {
+ final CParameters capabilityToSerialize = new CParametersBuilder().addAugmentation(CParameters1.class, new CParameters1Builder().setAddPathCapability(
+ new AddPathCapabilityBuilder().setAddressFamilies(new ArrayList<AddressFamilies>()).build()).build()).build();
+
+ final ByteBuf bytes = this.parseWrongBytes.copy();
+ final AddPathCapabilityHandler handler = new AddPathCapabilityHandler(this.afiRegistry, this.safiRegistry);
+ final CParameters newCaps = handler.parseCapability(bytes);
+ assertEquals(capabilityToSerialize.hashCode(), newCaps.hashCode());
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testUnhandledAfi() {
+ final List<AddressFamilies> family = new ArrayList<AddressFamilies>();
+ family.add(new AddressFamiliesBuilder().setAfi(this.afi).setSafi(this.safi).setSendReceive(SendReceive.forValue(2)).build());
+
+ final CParameters capabilityToSerialize = new CParametersBuilder().addAugmentation(CParameters1.class, new CParameters1Builder().setAddPathCapability(
+ new AddPathCapabilityBuilder().setAddressFamilies(family).build()).build()).build();
+
+ final ByteBuf bytes = Unpooled.buffer();
+ final AddPathCapabilityHandler handler = new AddPathCapabilityHandler(this.afirExpection, this.safiRegistry);
+ handler.serializeCapability(capabilityToSerialize, bytes);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testUnhandledSafi() {
+ final List<AddressFamilies> family = new ArrayList<AddressFamilies>();
+ family.add(new AddressFamiliesBuilder().setAfi(this.afi).setSafi(this.safi).setSendReceive(SendReceive.forValue(3)).build());
+
+ final CParameters capabilityToSerialize = new CParametersBuilder().addAugmentation(CParameters1.class, new CParameters1Builder().setAddPathCapability(
+ new AddPathCapabilityBuilder().setAddressFamilies(family).build()).build()).build();
+
+ final ByteBuf bytes = Unpooled.buffer();
+ final AddPathCapabilityHandler handler = new AddPathCapabilityHandler(this.afiRegistry, this.safirException);
+ handler.serializeCapability(capabilityToSerialize, bytes);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testUnhandledSendReceive() {
+ final List<AddressFamilies> family = new ArrayList<AddressFamilies>();
+ family.add(new AddressFamiliesBuilder().setAfi(this.afi).setSafi(this.safi).setSendReceive(SendReceive.forValue(4)).build());
+
+ final CParameters capabilityToSerialize = new CParametersBuilder().addAugmentation(CParameters1.class, new CParameters1Builder().setAddPathCapability(
+ new AddPathCapabilityBuilder().setAddressFamilies(family).build()).build()).build();
+
+ final ByteBuf bytes = Unpooled.buffer();
+ final AddPathCapabilityHandler handler = new AddPathCapabilityHandler(this.afiRegistry, this.safiRegistry);
+ handler.serializeCapability(capabilityToSerialize, bytes);
+ }
+
+ @Test
+ public void noSerializationTest() {
+ final CParameters capabilityNoAugmentation = new CParametersBuilder().addAugmentation(CParameters1.class, null).build();
+ final CParameters capabilityNoMP = new CParametersBuilder().addAugmentation(CParameters1.class, new CParameters1Builder().build()).build();
+
+ final ByteBuf bytes = Unpooled.buffer();
+ final AddPathCapabilityHandler handler = new AddPathCapabilityHandler(this.afiRegistry, this.safirException);
+ handler.serializeCapability(capabilityNoAugmentation, bytes);
+ assertEquals(0, bytes.readableBytes());
+ handler.serializeCapability(capabilityNoMP, bytes);
+ assertEquals(0, bytes.readableBytes());
+ }
+}