BUG-353: add remote-as awareness 68/5468/5
authorRobert Varga <rovarga@cisco.com>
Wed, 26 Feb 2014 09:59:40 +0000 (10:59 +0100)
committerRobert Varga <rovarga@cisco.com>
Fri, 28 Feb 2014 09:31:28 +0000 (10:31 +0100)
This adds the configuration knob for the remote AS. Furthermore it adds
validation of the AS advertizement during negotiation. Drive-by fixes
include introduction of buildErrorNotify() and rename of fields inside
BGPObjectComparator for clarity.

Change-Id: Ie60e0633d84a8a6a239517600e4666dee2a0d3ed
Signed-off-by: Robert Varga <rovarga@cisco.com>
17 files changed:
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AsNumberUtil.java [new file with mode: 0644]
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/BGPSession.java
bgp/rib-impl-config/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java
bgp/rib-impl-config/src/main/yang/bgp-rib-impl.yang
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPDispatcherImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPObjectComparator.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionNegotiator.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSessionNegotiatorFactory.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BGPDispatcher.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/FSMTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SynchronizationTest.java
bgp/rib-mock/src/main/java/org/opendaylight/protocol/bgp/rib/mock/EventBusRegistration.java
bgp/testtool/src/main/java/org/opendaylight/protocol/bgp/testtool/Main.java
bgp/testtool/src/test/java/org/opendaylight/protocol/bgp/testtool/BGPSpeakerMock.java
integration-tests/src/test/java/org/opendaylight/protocol/integration/bgp/ParserToSalTest.java

diff --git a/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AsNumberUtil.java b/bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/AsNumberUtil.java
new file mode 100644 (file)
index 0000000..3b83f28
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 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;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.CParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.c.parameters.As4BytesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.bgp.parameters.c.parameters.as4.bytes._case.As4BytesCapability;
+
+public final class AsNumberUtil {
+       private AsNumberUtil() {
+               throw new UnsupportedOperationException("Utility class should never be instantiated");
+       }
+
+       public static AsNumber advertizedAsNumber(final Open open) {
+               // Look for AS4 capability very defensively
+               final List<BgpParameters> params = open.getBgpParameters();
+               if (params != null) {
+                       for (BgpParameters p : params) {
+                               final CParameters cp = p.getCParameters();
+                               if (cp != null && cp instanceof As4BytesCase) {
+                                       final As4BytesCapability capa = ((As4BytesCase)cp).getAs4BytesCapability();
+                                       if (capa != null) {
+                                               return capa.getAsNumber();
+                                       }
+                               }
+                       }
+               }
+
+               // Fallback to whatever is in the header
+               return new AsNumber(open.getMyAsNumber().longValue());
+       }
+}
index 9c0de8f7390c0023c8e44af9260e2f11ee508513..3c62d2f334618e39e1da989babfb3d06904c2e42 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.protocol.bgp.parser;
 import java.util.Set;
 
 import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
@@ -35,4 +36,11 @@ public interface BGPSession extends ProtocolSession<Notification> {
         * @return Peer's BGP Router ID.
         */
        byte[] getBgpId();
+
+       /**
+        * Return the AS number which the peer advertizes.
+        * 
+        * @return Peer's AS Number
+        */
+       AsNumber getAsNumber();
 }
index 093901bf3e5e53ab7763c01a455ff3e435b0b1a9..c983e04eaa59f964517990c6e905c16577892089 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.protocol.bgp.rib.impl.BGPPeer;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
+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.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParametersBuilder;
@@ -102,7 +103,15 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
                                                        new MultiprotocolCapabilityBuilder(t).build()).build()).build());
                }
 
+               // Remote AS number defaults to our local AS
+               final AsNumber remoteAs;
+               if (getRemoteAs() != null) {
+                       remoteAs = new AsNumber(getRemoteAs());
+               } else {
+                       remoteAs = r.getLocalAs();
+               }
+
                return new BGPPeer(peerName(getHost()), createAddress(),
-                               new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), tlvs), r);
+                               new BGPSessionPreferences(r.getLocalAs(), getHoldtimer(), r.getBgpIdentifier(), tlvs), remoteAs, r);
        }
 }
index d671a05121529fb1b0009c8945405be3e2b1bab7..720a11ff2d093e350bad9d12cb4470d958cf054f 100644 (file)
@@ -189,6 +189,13 @@ module bgp-rib-impl {
                 }
             }
 
+            leaf remote-as {
+                description
+                    "Expected remote AS number. If not present, it is assumed
+                    to be the same as our local AS number.";
+                type uint32;
+            }
+
             container rib {
                 uses config:service-ref {
                     refine type {
@@ -257,13 +264,13 @@ module bgp-rib-impl {
             }
 
             leaf local-as {
-               description "Our local AS number. Needed by best selection path attribute.";
+                description "Our local AS number. Needed by best selection path attribute.";
                 type uint32;
                 mandatory true;
             }
 
             leaf bgp-id {
-                       description "Our local BGP identifier. Needed by best selection path attribute.";
+                description "Our local BGP identifier. Needed by best selection path attribute.";
                 mandatory true;
                 type inet:ipv4-address;
             }
index e159c7568e7b77d94631e9dbd8f1ca997f985464..044e239ffa871aa77c318f78265996deac584344 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.protocol.framework.AbstractDispatcher;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 
 /**
  * Implementation of BGPDispatcher.
@@ -40,8 +41,8 @@ public final class BGPDispatcherImpl extends AbstractDispatcher<BGPSessionImpl,
 
        @Override
        public Future<BGPSessionImpl> createClient(final InetSocketAddress address, final BGPSessionPreferences preferences,
-                       final BGPSessionListener listener, final ReconnectStrategy strategy) {
-               final BGPSessionNegotiatorFactory snf = new BGPSessionNegotiatorFactory(this.timer, preferences);
+                       final AsNumber remoteAs, final BGPSessionListener listener, final ReconnectStrategy strategy) {
+               final BGPSessionNegotiatorFactory snf = new BGPSessionNegotiatorFactory(this.timer, preferences, remoteAs);
                final SessionListenerFactory<BGPSessionListener> slf = new SessionListenerFactory<BGPSessionListener>() {
                        @Override
                        public BGPSessionListener getSessionListener() {
@@ -60,10 +61,10 @@ public final class BGPDispatcherImpl extends AbstractDispatcher<BGPSessionImpl,
 
        @Override
        public Future<Void> createReconnectingClient(final InetSocketAddress address,
-                       final BGPSessionPreferences preferences, final BGPSessionListener listener,
-                       final ReconnectStrategyFactory connectStrategyFactory,
+                       final BGPSessionPreferences preferences, final AsNumber remoteAs,
+                       final BGPSessionListener listener, final ReconnectStrategyFactory connectStrategyFactory,
                        final ReconnectStrategy reestablishStrategy) {
-               final BGPSessionNegotiatorFactory snf = new BGPSessionNegotiatorFactory(this.timer, preferences);
+               final BGPSessionNegotiatorFactory snf = new BGPSessionNegotiatorFactory(this.timer, preferences, remoteAs);
                final SessionListenerFactory<BGPSessionListener> slf = new SessionListenerFactory<BGPSessionListener>() {
                        @Override
                        public BGPSessionListener getSessionListener() {
index 93493efc231c97c731aa552187a95761b137c4a8..9dc76fb465d60fef1094580d047c50ac155a1958 100644 (file)
@@ -31,17 +31,13 @@ import com.google.common.net.InetAddresses;
  * @param <T> Actual object state reference
  */
 final class BGPObjectComparator implements Comparator<PathAttributes> {
-
+       private final byte[] localId, remoteId;
        private final AsNumber ourAS;
 
-       private final byte[] id1;
-
-       private final byte[] id2;
-
        public BGPObjectComparator(final AsNumber ourAs, final Ipv4Address localId, final byte[] remoteId) {
-               this.ourAS = ourAs;
-               this.id1 = InetAddresses.forString(localId.getValue()).getAddress();
-               this.id2 = Preconditions.checkNotNull(remoteId);
+               this.ourAS = Preconditions.checkNotNull(ourAs);
+               this.localId = InetAddresses.forString(localId.getValue()).getAddress();
+               this.remoteId = Preconditions.checkNotNull(remoteId);
        }
 
        @Override
@@ -52,7 +48,7 @@ final class BGPObjectComparator implements Comparator<PathAttributes> {
                if (o2 == null) {
                        return -1;
                }
-               if (o1.equals(o2) && Arrays.equals(this.id1, this.id2)) {
+               if (o1.equals(o2) && Arrays.equals(this.localId, this.remoteId)) {
                        return 0;
                }
                // 1. prefer path with accessible nexthop
@@ -121,8 +117,8 @@ final class BGPObjectComparator implements Comparator<PathAttributes> {
                // The router ID is the highest IP address on the router, with preference given to loopback addresses.
                // If a path contains route reflector (RR) attributes, the originator ID is substituted for the router ID in the
                // path selection process.
-               byte[] oid1 = this.id1;
-               byte[] oid2 = this.id2;
+               byte[] oid1 = this.localId;
+               byte[] oid2 = this.remoteId;
                if (o1.getOriginatorId() != null) {
                        oid1 = InetAddresses.forString(o1.getOriginatorId().getValue()).getAddress();
                }
index 9b44e0244bfc1b51b4a44b5b26190e080f3873cd..8b4e49527704e8a6bf6bb191ab588407d82b7363 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.protocol.bgp.parser.BGPTerminationReason;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.protocol.bgp.rib.spi.Peer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
@@ -51,10 +52,10 @@ public final class BGPPeer implements BGPSessionListener, Peer, AutoCloseable {
        private BGPSession session;
 
        public BGPPeer(final String name, final InetSocketAddress address, final BGPSessionPreferences prefs,
-                       final RIB rib) {
+                       final AsNumber remoteAs, final RIB rib) {
                this.rib = Preconditions.checkNotNull(rib);
                this.name = Preconditions.checkNotNull(name);
-               cf = rib.getDispatcher().createReconnectingClient(address, prefs, this, rib.getTcpStrategyFactory(), rib.getSessionStrategy());
+               cf = rib.getDispatcher().createReconnectingClient(address, prefs, remoteAs, this, rib.getTcpStrategyFactory(), rib.getSessionStrategy());
        }
 
        @Override
index 1f13e13f3e9a930e6a26d42dde74f8e5c08d8af6..e40f60f3d3d086f3e4dbf7a421b464f072d6f799 100644 (file)
@@ -19,12 +19,14 @@ import java.util.concurrent.TimeUnit;
 
 import javax.annotation.concurrent.GuardedBy;
 
+import org.opendaylight.protocol.bgp.parser.AsNumberUtil;
 import org.opendaylight.protocol.bgp.parser.BGPError;
 import org.opendaylight.protocol.bgp.parser.BGPSession;
 import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
 import org.opendaylight.protocol.bgp.parser.BGPTerminationReason;
 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
 import org.opendaylight.protocol.framework.AbstractProtocolSession;
+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.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.KeepaliveBuilder;
@@ -59,8 +61,6 @@ public class BGPSessionImpl extends AbstractProtocolSession<Notification> implem
 
        private static final Notification KEEP_ALIVE = new KeepaliveBuilder().build();
 
-       private static int holdTimerValue = DEFAULT_HOLD_TIMER_VALUE;
-
        /**
         * Internal session state.
         */
@@ -108,10 +108,11 @@ public class BGPSessionImpl extends AbstractProtocolSession<Notification> implem
        @GuardedBy("this")
        private State state = State.OpenConfirm;
 
-       private final int keepAlive;
 
        private final Set<BgpTableType> tableTypes;
-
+       private final int holdTimerValue;
+       private final int keepAlive;
+       private final AsNumber asNumber;
        private final Ipv4Address bgpId;
 
        BGPSessionImpl(final Timer timer, final BGPSessionListener listener, final Channel channel, final Open remoteOpen) {
@@ -119,7 +120,8 @@ public class BGPSessionImpl extends AbstractProtocolSession<Notification> implem
                this.stateTimer = Preconditions.checkNotNull(timer);
                this.channel = Preconditions.checkNotNull(channel);
                this.keepAlive = remoteOpen.getHoldTimer() / 3;
-               holdTimerValue = remoteOpen.getHoldTimer();
+               this.holdTimerValue = remoteOpen.getHoldTimer();
+               this.asNumber = AsNumberUtil.advertizedAsNumber(remoteOpen);
 
                final Set<TablesKey> tts = Sets.newHashSet();
                final Set<BgpTableType> tats = Sets.newHashSet();
@@ -316,7 +318,13 @@ public class BGPSessionImpl extends AbstractProtocolSession<Notification> implem
                return this.state;
        }
 
-       public byte[] getBgpId() {
+       @Override
+       public final byte[] getBgpId() {
                return this.bgpId.getValue().getBytes();
        }
+
+       @Override
+       public final AsNumber getAsNumber() {
+               return this.asNumber;
+       }
 }
index 7a89348ff11f462bfb5b2ab5c0d46127b14fbda5..01f54f8793fe8a194e1d31e517eceb8b5de1a580 100644 (file)
@@ -18,11 +18,13 @@ import java.util.concurrent.TimeUnit;
 
 import javax.annotation.concurrent.GuardedBy;
 
+import org.opendaylight.protocol.bgp.parser.AsNumberUtil;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.BGPError;
 import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
 import org.opendaylight.protocol.framework.AbstractSessionNegotiator;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.KeepaliveBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
@@ -63,12 +65,10 @@ public final class BGPSessionNegotiator extends AbstractSessionNegotiator<Notifi
        }
 
        private static final Logger LOG = LoggerFactory.getLogger(BGPSessionNegotiator.class);
+       private final BGPSessionPreferences localPref;
        private final BGPSessionListener listener;
+       private final AsNumber remoteAs;
        private final Timer timer;
-       private final BGPSessionPreferences localPref;
-
-       @GuardedBy("this")
-       private Open remotePref;
 
        @GuardedBy("this")
        private State state = State.Idle;
@@ -77,10 +77,11 @@ public final class BGPSessionNegotiator extends AbstractSessionNegotiator<Notifi
        private BGPSessionImpl session;
 
        public BGPSessionNegotiator(final Timer timer, final Promise<BGPSessionImpl> promise, final Channel channel,
-                       final BGPSessionPreferences initialPrefs, final BGPSessionListener listener) {
+                       final BGPSessionPreferences initialPrefs, final AsNumber remoteAs, final BGPSessionListener listener) {
                super(promise, channel);
                this.listener = Preconditions.checkNotNull(listener);
                this.localPref = Preconditions.checkNotNull(initialPrefs);
+               this.remoteAs = Preconditions.checkNotNull(remoteAs);
                this.timer = Preconditions.checkNotNull(timer);
        }
 
@@ -97,8 +98,7 @@ public final class BGPSessionNegotiator extends AbstractSessionNegotiator<Notifi
                        public void run(final Timeout timeout) throws Exception {
                                synchronized (lock) {
                                        if (BGPSessionNegotiator.this.state != State.Finished) {
-                                               BGPSessionNegotiator.this.sendMessage(new NotifyBuilder().setErrorCode(BGPError.HOLD_TIMER_EXPIRED.getCode()).setErrorSubcode(
-                                                               BGPError.HOLD_TIMER_EXPIRED.getSubcode()).build());
+                                               BGPSessionNegotiator.this.sendMessage(buildErrorNotify(BGPError.HOLD_TIMER_EXPIRED));
                                                negotiationFailed(new BGPDocumentedException("HoldTimer expired", BGPError.FSM_ERROR));
                                                BGPSessionNegotiator.this.state = State.Finished;
                                        }
@@ -114,9 +114,8 @@ public final class BGPSessionNegotiator extends AbstractSessionNegotiator<Notifi
                switch (this.state) {
                case Finished:
                case Idle:
-                       final Notify fsmError = new NotifyBuilder().setErrorCode(BGPError.FSM_ERROR.getCode()).setErrorSubcode(
-                                       BGPError.FSM_ERROR.getSubcode()).build();
-                       this.sendMessage(fsmError);
+                       this.sendMessage(buildErrorNotify(BGPError.FSM_ERROR));
+                       // FIXME: is something missing here? (at least an explanation why fall-through is okay
                case OpenConfirm:
                        if (msg instanceof Keepalive) {
                                negotiationSuccessful(this.session);
@@ -137,29 +136,39 @@ public final class BGPSessionNegotiator extends AbstractSessionNegotiator<Notifi
 
                // Catch-all for unexpected message
                LOG.warn("Channel {} state {} unexpected message {}", this.channel, this.state, msg);
-               this.sendMessage(new NotifyBuilder().setErrorCode(BGPError.FSM_ERROR.getCode()).setErrorSubcode(BGPError.FSM_ERROR.getSubcode()).build());
+               this.sendMessage(buildErrorNotify(BGPError.FSM_ERROR));
                negotiationFailed(new BGPDocumentedException("Unexpected message", BGPError.FSM_ERROR));
                this.state = State.Finished;
        }
 
+       private static Notify buildErrorNotify(final BGPError err) {
+               return new NotifyBuilder().setErrorCode(err.getCode()).setErrorSubcode(err.getSubcode()).build();
+       }
+
        private void handleOpen(final Open openObj) {
+               final AsNumber as = AsNumberUtil.advertizedAsNumber(openObj);
+               if (!remoteAs.equals(as)) {
+                       LOG.info("Unexpected remote AS number. Expecting {}, got {}", remoteAs, as);
+                       this.sendMessage(buildErrorNotify(BGPError.BAD_PEER_AS));
+                       negotiationFailed(new BGPDocumentedException("Peer AS number mismatch", BGPError.BAD_PEER_AS));
+                       this.state = State.Finished;
+                       return;
+               }
+
                final List<BgpParameters> prefs = openObj.getBgpParameters();
                if (prefs != null && !prefs.isEmpty()) {
                        if (!prefs.containsAll(this.localPref.getParams())) {
                                LOG.info("Open message unacceptable. Check the configuration of BGP speaker.");
                        }
-                       this.remotePref = openObj;
                        this.sendMessage(new KeepaliveBuilder().build());
-                       this.session = new BGPSessionImpl(this.timer, this.listener, this.channel, this.remotePref);
+                       this.session = new BGPSessionImpl(this.timer, this.listener, this.channel, openObj);
                        this.state = State.OpenConfirm;
-                       LOG.debug("Channel {} moved to OpenConfirm state with remote proposal {}", this.channel, this.remotePref);
+                       LOG.debug("Channel {} moved to OpenConfirm state with remote proposal {}", this.channel, openObj);
                        return;
                }
-               final Notify ntf = new NotifyBuilder().setErrorCode(BGPError.UNSPECIFIC_OPEN_ERROR.getCode()).setErrorSubcode(
-                               BGPError.UNSPECIFIC_OPEN_ERROR.getSubcode()).build();
-               this.sendMessage(ntf);
-               negotiationFailed(new BGPDocumentedException("Open message unacceptable. Check the configuration of BGP speaker.", BGPError.forValue(
-                               ntf.getErrorCode(), ntf.getErrorSubcode())));
+
+               this.sendMessage(buildErrorNotify(BGPError.UNSPECIFIC_OPEN_ERROR));
+               negotiationFailed(new BGPDocumentedException("Open message unacceptable. Check the configuration of BGP speaker.", BGPError.UNSPECIFIC_OPEN_ERROR));
                this.state = State.Finished;
        }
 
index 068bcc47e243dfe75ba97639b1d39a61f885eaa2..ffe725e58b082763ddf594aaff5e3e521ba68752 100644 (file)
@@ -16,22 +16,25 @@ import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 import org.opendaylight.protocol.framework.SessionNegotiator;
 import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
 import com.google.common.base.Preconditions;
 
 public final class BGPSessionNegotiatorFactory implements SessionNegotiatorFactory<Notification, BGPSessionImpl, BGPSessionListener> {
        private final BGPSessionPreferences initialPrefs;
+       private final AsNumber remoteAs;
        private final Timer timer;
 
-       public BGPSessionNegotiatorFactory(final Timer timer, final BGPSessionPreferences initialPrefs) {
+       public BGPSessionNegotiatorFactory(final Timer timer, final BGPSessionPreferences initialPrefs, final AsNumber remoteAs) {
                this.timer = Preconditions.checkNotNull(timer);
                this.initialPrefs = Preconditions.checkNotNull(initialPrefs);
+               this.remoteAs = Preconditions.checkNotNull(remoteAs);
        }
 
        @Override
        public SessionNegotiator<BGPSessionImpl> getSessionNegotiator(final SessionListenerFactory<BGPSessionListener> factory,
                        final Channel channel, final Promise<BGPSessionImpl> promise) {
-               return new BGPSessionNegotiator(this.timer, promise, channel, this.initialPrefs, factory.getSessionListener());
+               return new BGPSessionNegotiator(this.timer, promise, channel, this.initialPrefs, remoteAs, factory.getSessionListener());
        }
 }
index 7a11130b788024db5f1300bb7c043d8adafe5fe4..f474def0cfa06766eada14660c6711fed2032faa 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.protocol.bgp.parser.BGPSession;
 import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 
 /**
  * Dispatcher class for creating BGP clients.
@@ -29,9 +30,9 @@ public interface BGPDispatcher {
         * @param listener BGP message listener
         * @return Future promising a client session
         */
-       Future<? extends BGPSession> createClient(InetSocketAddress address, BGPSessionPreferences preferences, BGPSessionListener listener,
-                       final ReconnectStrategy strategy);
+       Future<? extends BGPSession> createClient(InetSocketAddress address, BGPSessionPreferences preferences, AsNumber remoteAs,
+                       BGPSessionListener listener, ReconnectStrategy strategy);
 
-       Future<Void> createReconnectingClient(InetSocketAddress address, BGPSessionPreferences preferences, BGPSessionListener listener,
-                       ReconnectStrategyFactory connectStrategyFactory, final ReconnectStrategy reestablishStrategy);
+       Future<Void> createReconnectingClient(InetSocketAddress address, BGPSessionPreferences preferences, AsNumber remoteAs,
+                       BGPSessionListener listener, ReconnectStrategyFactory connectStrategyFactory, ReconnectStrategy reestablishStrategy);
 }
index 12d986e9614e1137737fe787eb814da952cb3810..ae5f2f8a7bbfc59313100b453efcb424a7cad389 100644 (file)
@@ -88,7 +88,8 @@ public class FSMTest {
 
                final ChannelFuture f = mock(ChannelFuture.class);
                doReturn(null).when(f).addListener(any(GenericFutureListener.class));
-               this.clientSession = new BGPSessionNegotiator(new HashedWheelTimer(), new DefaultPromise<BGPSessionImpl>(GlobalEventExecutor.INSTANCE), this.speakerListener, prefs, new SimpleSessionListener());
+               this.clientSession = new BGPSessionNegotiator(new HashedWheelTimer(), new DefaultPromise<BGPSessionImpl>(GlobalEventExecutor.INSTANCE),
+                               this.speakerListener, prefs, new AsNumber(30L), new SimpleSessionListener());
                doAnswer(new Answer<Object>() {
                        @Override
                        public Object answer(final InvocationOnMock invocation) {
index 85e46cded97a2bb3cd84f299ffead65ea6e066af..ed86ad3c616e53ffff585da4812ba2d9d7fe09d6 100644 (file)
@@ -15,6 +15,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.protocol.bgp.parser.BGPSession;
 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+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.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateAddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateSubsequentAddressFamily;
@@ -94,6 +95,11 @@ public class SynchronizationTest {
                        public byte[] getBgpId() {
                                return new byte[] { (byte) 127, 0, 0, 1 };
                        }
+
+                       @Override
+                       public AsNumber getAsNumber() {
+                               return new AsNumber(30L);
+                       }
                }, this.listener, types);
        }
 
index 8401b7b723ffdc98bf400cd43c5eeb4ecce6712a..60e8e1d933a9066e5525915454d02399a9c5728f 100644 (file)
@@ -13,6 +13,7 @@ import java.util.Set;
 import org.opendaylight.protocol.bgp.parser.BGPSession;
 import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
@@ -92,6 +93,11 @@ final class EventBusRegistration extends AbstractListenerRegistration<BGPSession
                                public byte[] getBgpId() {
                                        return new byte[] { (byte) 127, 0, 0, 1 };
                                }
+
+                               @Override
+                               public AsNumber getAsNumber() {
+                                       return new AsNumber(30L);
+                               }
                        });
                } else if (!(message instanceof Keepalive)) {
                        listener.onMessage(null, message);
index 05c9a75d94495b3c18657571885b501809885a5f..a7fef42ddfa90c84cdea9b8e94bfd7bd7ff890a6 100644 (file)
@@ -108,7 +108,7 @@ public final class Main {
                LOG.debug("{} {} {}", address, sessionListener, proposal);
 
                final InetSocketAddress addr = address;
-               m.dispatcher.createClient(addr, proposal, sessionListener,
+               m.dispatcher.createClient(addr, proposal, as, sessionListener,
                                new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, RECONNECT_MILLIS));
        }
 }
index 5ccd87819e3cd9b1c4f052bd80c0b360931a70f4..298d723933dde0ba37592e8b5503e4de7768f835 100644 (file)
@@ -82,7 +82,7 @@ public class BGPSpeakerMock<M, S extends ProtocolSession<M>, L extends SessionLi
 
                final BGPSessionPreferences prefs = new BGPSessionProposalImpl((short) 90, new AsNumber(72L), new Ipv4Address("127.0.0.2"), tables).getProposal();
 
-               final SessionNegotiatorFactory<Notification, BGPSessionImpl, BGPSessionListener> snf = new BGPSessionNegotiatorFactory(new HashedWheelTimer(), prefs);
+               final SessionNegotiatorFactory<Notification, BGPSessionImpl, BGPSessionListener> snf = new BGPSessionNegotiatorFactory(new HashedWheelTimer(), prefs, new AsNumber(72L));
 
                final BGPSpeakerMock<Notification, BGPSessionImpl, BGPSessionListener> mock = new BGPSpeakerMock<>(snf, new BGPHandlerFactory(ServiceLoaderBGPExtensionProviderContext.createConsumerContext().getMessageRegistry()), new DefaultPromise<BGPSessionImpl>(GlobalEventExecutor.INSTANCE));
 
index 0c06a4cfbf427e22e32db7a137464d833335f22e..5fb31c3a499d3a2503c79bbccb06d1115c6f1053 100644 (file)
@@ -159,7 +159,7 @@ public class ParserToSalTest {
                }).when(this.mockedTransaction).readOperationalData(Matchers.any(InstanceIdentifier.class));
 
                Mockito.doReturn(GlobalEventExecutor.INSTANCE.newSucceededFuture(null)).when(dispatcher).
-               createReconnectingClient(Mockito.any(InetSocketAddress.class), Mockito.any(BGPSessionPreferences.class),
+               createReconnectingClient(Mockito.any(InetSocketAddress.class), Mockito.any(BGPSessionPreferences.class), Mockito.any(AsNumber.class),
                                Mockito.any(BGPSessionListener.class), Mockito.eq(tcpStrategyFactory), Mockito.eq(sessionStrategy));
 
                ext = new SimpleRIBExtensionProviderContext();
@@ -179,7 +179,7 @@ public class ParserToSalTest {
        private void runTestWithTables(final List<BgpTableType> tables) {
                final RIBImpl rib = new RIBImpl(new RibId("testRib"), new AsNumber(72L), new Ipv4Address("127.0.0.1"), ext,
                                this.dispatcher, this.tcpStrategyFactory, this.sessionStrategy, this.providerService, tables);
-               final BGPPeer peer = new BGPPeer("peer-" + this.mock.toString(), null, null, rib);
+               final BGPPeer peer = new BGPPeer("peer-" + this.mock.toString(), null, null, rib.getLocalAs(), rib);
 
                ListenerRegistration<?> reg = this.mock.registerUpdateListener(peer);
                reg.close();