BUG-4617: BGP Flow-Spec Redirect to IP Action 63/30063/3
authorMilos Fabian <milfabia@cisco.com>
Wed, 18 Nov 2015 14:00:33 +0000 (15:00 +0100)
committerMilos Fabian <milfabia@cisco.com>
Tue, 24 Nov 2015 10:11:43 +0000 (10:11 +0000)
-adds support for BGP FS Redirect to IP action
-implementation is based on draft-ietf-idr-flowspec-redirect-ip-02
-registered under Ex. comm type/subtype as per
https://tools.ietf.org/html/draft-ietf-idr-flowspec-redirect-ip-00#section-7

Change-Id: If889e1b65d944c71b85e0d27c57af4be7e08af6c
Signed-off-by: Milos Fabian <milfabia@cisco.com>
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/BGPActivator.java
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/extended/communities/RedirectIpNextHopEcHandler.java [new file with mode: 0644]
bgp/flowspec/src/test/java/org/opendaylight/protocol/bgp/flowspec/extended/communities/FSExtendedCommunitiesTest.java

index 2f3e44cdf9daa934f076fd942afcb757c0b771e8..fb04f4f77684aa6ae53fb8cc8b85ce8fe3f52846 100644 (file)
@@ -11,6 +11,7 @@ import java.util.ArrayList;
 import java.util.List;
 import org.opendaylight.protocol.bgp.flowspec.extended.communities.RedirectAsFourOctetEcHandler;
 import org.opendaylight.protocol.bgp.flowspec.extended.communities.RedirectAsTwoOctetEcHandler;
+import org.opendaylight.protocol.bgp.flowspec.extended.communities.RedirectIpNextHopEcHandler;
 import org.opendaylight.protocol.bgp.flowspec.extended.communities.RedirectIpv4EcHandler;
 import org.opendaylight.protocol.bgp.flowspec.extended.communities.RedirectIpv6EcHandler;
 import org.opendaylight.protocol.bgp.flowspec.extended.communities.TrafficActionEcHandler;
@@ -25,6 +26,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.FlowspecRoutes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectAs4ExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpv4ExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpv6ExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.TrafficActionExtendedCommunityCase;
@@ -91,6 +93,11 @@ public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
         regs.add(context.registerExtendedCommunitySerializer(RedirectIpv4ExtendedCommunityCase.class, redirectIpv4Handler));
         regs.add(context.registerExtendedCommunitySerializer(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.ipv6.routes.flowspec.ipv6.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpv4ExtendedCommunityCase.class, redirectIpv4Handler));
 
+        final RedirectIpNextHopEcHandler redirectIpNhHandler = new RedirectIpNextHopEcHandler();
+        regs.add(context.registerExtendedCommunityParser(redirectIpNhHandler.getType(true), redirectIpNhHandler.getSubType(), redirectIpNhHandler));
+        regs.add(context.registerExtendedCommunitySerializer(RedirectIpNhExtendedCommunityCase.class, redirectIpNhHandler));
+        regs.add(context.registerExtendedCommunitySerializer(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.ipv6.routes.flowspec.ipv6.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCase.class, redirectIpNhHandler));
+
         return regs;
     }
 }
diff --git a/bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/extended/communities/RedirectIpNextHopEcHandler.java b/bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/extended/communities/RedirectIpNextHopEcHandler.java
new file mode 100644 (file)
index 0000000..7358300
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.extended.communities;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.extended.community.ExtendedCommunityParser;
+import org.opendaylight.protocol.bgp.parser.spi.extended.community.ExtendedCommunitySerializer;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.protocol.util.Ipv4Util;
+import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.redirect.ip.nh.extended.community.RedirectIpNhExtendedCommunity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.redirect.ip.nh.extended.community.RedirectIpNhExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.ExtendedCommunity;
+
+public class RedirectIpNextHopEcHandler implements ExtendedCommunityParser, ExtendedCommunitySerializer {
+
+    //https://tools.ietf.org/html/draft-ietf-idr-flowspec-redirect-ip-00#section-7
+    private static final int TYPE = 8;
+
+    private static final int SUBTYPE = 0;
+
+    private static final byte COPY = 0x1;
+
+    @Override
+    public void serializeExtendedCommunity(final ExtendedCommunity extendedCommunity, final ByteBuf byteAggregator) {
+        Preconditions.checkArgument(extendedCommunity instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.RedirectIpNhExtendedCommunity,
+                "The extended community %s is not RedirectIpNhExtendedCommunityCase type.", extendedCommunity);
+        final RedirectIpNhExtendedCommunity redirect = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.RedirectIpNhExtendedCommunity) extendedCommunity).getRedirectIpNhExtendedCommunity();
+        final IpAddress nextHopAddress = redirect.getNextHopAddress();
+        if (nextHopAddress.getIpv4Address() != null) {
+            ByteBufWriteUtil.writeIpv4Address(nextHopAddress.getIpv4Address(), byteAggregator);
+        } else {
+            ByteBufWriteUtil.writeIpv6Address(nextHopAddress.getIpv6Address(), byteAggregator);
+        }
+        ByteBufWriteUtil.writeUnsignedShort((redirect.isCopy() == null || !redirect.isCopy()) ? 0 : 1, byteAggregator);
+    }
+
+    @Override
+    public ExtendedCommunity parseExtendedCommunity(final ByteBuf buffer) throws BGPDocumentedException, BGPParsingException {
+        final RedirectIpNhExtendedCommunityBuilder builder = new RedirectIpNhExtendedCommunityBuilder();
+        if (buffer.readableBytes() > Ipv6Util.IPV6_LENGTH ) {
+            builder.setNextHopAddress(new IpAddress(Ipv6Util.addressForByteBuf(buffer)));
+        } else {
+            builder.setNextHopAddress(new IpAddress(Ipv4Util.addressForByteBuf(buffer)));
+        }
+        builder.setCopy((buffer.readUnsignedShort() & COPY) == 1);
+        return new RedirectIpNhExtendedCommunityCaseBuilder().setRedirectIpNhExtendedCommunity(builder.build()).build();
+    }
+
+    @Override
+    public int getType(final boolean isTransitive) {
+        return TYPE;
+    }
+
+    @Override
+    public int getSubType() {
+        return SUBTYPE;
+    }
+
+}
index c8febf1a100b50c267982cf91a2aef45a9ce3122..d576dace4a85049c6bfaa034980a0912785d40f5 100644 (file)
@@ -21,11 +21,13 @@ import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
 import org.opendaylight.protocol.bgp.parser.spi.extended.community.ExtendedCommunityRegistry;
 import org.opendaylight.protocol.bgp.parser.spi.pojo.SimpleBGPExtensionProviderContext;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
 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.redirect.as4.extended.community.RedirectAs4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.redirect.extended.community.RedirectExtendedCommunityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.redirect.ip.nh.extended.community.RedirectIpNhExtendedCommunityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.redirect.ipv4.extended.community.RedirectIpv4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.redirect.ipv6.extended.community.RedirectIpv6Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.traffic.action.extended.community.TrafficActionExtendedCommunityBuilder;
@@ -35,6 +37,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectAs4ExtendedCommunityCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectExtendedCommunityCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectIpv4ExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectIpv4ExtendedCommunityCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.extended.communities.extended.community.RedirectIpv6ExtendedCommunityCase;
@@ -66,6 +70,11 @@ public class FSExtendedCommunitiesTest {
 
     private static final byte[] REDIRECT_IPV4 = {(byte)129, 8, 127, 0, 0, 1, 0, 126};
 
+    private static final byte[] REDIRECT_NH_IPV4 = {8, 0, 127, 0, 0, 1, 0, 1};
+
+    private static final byte[] REDIRECT_NH_IPV6 = {8, 0, 0x20, (byte) 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0, 0};
+
     private ExtendedCommunityRegistry registry;
     private BGPActivator act;
 
@@ -241,4 +250,50 @@ public class FSExtendedCommunitiesTest {
         Assert.assertArrayEquals(REDIRECT_IPV4, output.array());
     }
 
+    @Test
+    public void testRedirectIpv4NhParser() throws BGPDocumentedException, BGPParsingException {
+        final RedirectIpNhExtendedCommunityCase redirect = new RedirectIpNhExtendedCommunityCaseBuilder().setRedirectIpNhExtendedCommunity(
+                new RedirectIpNhExtendedCommunityBuilder().setNextHopAddress(new IpAddress(new Ipv4Address("127.0.0.1"))).setCopy(true).build()).build();
+
+        final ExtendedCommunities expected = new ExtendedCommunitiesBuilder().setExtendedCommunity(redirect).setTransitive(true).build();
+
+        final ExtendedCommunities parsed = registry.parseExtendedCommunity(Unpooled.copiedBuffer(REDIRECT_NH_IPV4));
+        Assert.assertEquals(expected, parsed);
+    }
+
+    @Test
+    public void testredirectIpv4NhSerializer() throws BGPDocumentedException, BGPParsingException {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCase redirect = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCaseBuilder().setRedirectIpNhExtendedCommunity(
+                new RedirectIpNhExtendedCommunityBuilder().setNextHopAddress(new IpAddress(new Ipv4Address("127.0.0.1"))).setCopy(true).build()).build();
+
+        final ExtendedCommunities expected = new ExtendedCommunitiesBuilder().setExtendedCommunity(redirect).setTransitive(true).build();
+
+        final ByteBuf output = Unpooled.buffer(REDIRECT_NH_IPV4.length);
+        registry.serializeExtendedCommunity(expected, output);
+        Assert.assertArrayEquals(REDIRECT_NH_IPV4, output.array());
+    }
+
+    @Test
+    public void testRedirectIpv6NhParser() throws BGPDocumentedException, BGPParsingException {
+        final RedirectIpNhExtendedCommunityCase redirect = new RedirectIpNhExtendedCommunityCaseBuilder().setRedirectIpNhExtendedCommunity(
+                new RedirectIpNhExtendedCommunityBuilder().setNextHopAddress(new IpAddress(new Ipv6Address("2001::1"))).setCopy(false).build()).build();
+
+        final ExtendedCommunities expected = new ExtendedCommunitiesBuilder().setExtendedCommunity(redirect).setTransitive(true).build();
+
+        final ExtendedCommunities parsed = registry.parseExtendedCommunity(Unpooled.copiedBuffer(REDIRECT_NH_IPV6));
+        Assert.assertEquals(expected, parsed);
+    }
+
+    @Test
+    public void testredirectIpv6NhSerializer() throws BGPDocumentedException, BGPParsingException {
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCase redirect = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.routes.flowspec.routes.flowspec.route.attributes.extended.communities.extended.community.RedirectIpNhExtendedCommunityCaseBuilder().setRedirectIpNhExtendedCommunity(
+                new RedirectIpNhExtendedCommunityBuilder().setNextHopAddress(new IpAddress(new Ipv6Address("2001::1"))).build()).build();
+
+        final ExtendedCommunities expected = new ExtendedCommunitiesBuilder().setExtendedCommunity(redirect).setTransitive(true).build();
+
+        final ByteBuf output = Unpooled.buffer(REDIRECT_NH_IPV6.length);
+        registry.serializeExtendedCommunity(expected, output);
+        Assert.assertArrayEquals(REDIRECT_NH_IPV6, output.array());
+    }
+
 }