import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
import org.opendaylight.protocol.bgp.rib.impl.spi.ReusableBGPPeer;
import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
+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;
}
@Override
- public BGPSessionListener getPeer(final IpAddress ip, final Ipv4Address sourceId, final Ipv4Address remoteId) throws BGPDocumentedException {
- return this.global.getPeer(ip, sourceId, remoteId);
+ public BGPSessionListener getPeer(final IpAddress ip, final Ipv4Address sourceId, final Ipv4Address remoteId, final AsNumber asNumber)
+ throws BGPDocumentedException {
+ return this.global.getPeer(ip, sourceId, remoteId, asNumber);
}
@Override
import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
import org.opendaylight.protocol.framework.AbstractSessionNegotiator;
import org.opendaylight.protocol.util.Values;
+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.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
}
try {
- final BGPSessionListener peer = this.registry.getPeer(getRemoteIp(), getSourceId(openObj, getPreferences()), getDestinationId(openObj, getPreferences()));
+ final BGPSessionListener peer = this.registry.getPeer(getRemoteIp(), getSourceId(openObj, getPreferences()),
+ getDestinationId(openObj, getPreferences()), getAsNumber(openObj, getPreferences()));
this.sendMessage(new KeepaliveBuilder().build());
this.session = new BGPSessionImpl(peer, this.channel, openObj, getPreferences(), this.registry);
this.state = State.OPEN_CONFIRM;
}
/**
+ * @param openMsg Open message received from remote BGP speaker
+ * @param preferences Local BGP speaker preferences
* @return BGP Id of device that accepted the connection
*/
protected abstract Ipv4Address getDestinationId(final Open openMsg, final BGPSessionPreferences preferences);
/**
- * @return BGP Id of device that initiated the connection
+ * @param openMsg Open message received from remote BGP speaker
+ * @param preferences Local BGP speaker preferences
+ * @return BGP Id of device that accepted the connection
*/
protected abstract Ipv4Address getSourceId(final Open openMsg, final BGPSessionPreferences preferences);
+ /**
+ * @param openMsg Open message received from remote BGP speaker
+ * @param preferences Local BGP speaker preferences
+ * @return AS Number of device that initiate connection
+ */
+ protected abstract AsNumber getAsNumber(final Open openMsg, final BGPSessionPreferences preferences);
+
public synchronized State getState() {
return this.state;
}
import io.netty.channel.Channel;
import io.netty.util.concurrent.Promise;
-
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionValidator;
+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.Open;
protected Ipv4Address getSourceId(final Open openMsg, final BGPSessionPreferences preferences) {
return openMsg.getBgpIdentifier();
}
+
+ @Override
+ protected AsNumber getAsNumber(Open openMsg, BGPSessionPreferences preferences) {
+ return preferences.getMyAs();
+ }
}
LOG.warn("Unexpected remote AS number. Expecting {}, got {}", this.remoteAs, as);
throw new BGPDocumentedException("Peer AS number mismatch", BGPError.BAD_PEER_AS);
}
+ //https://tools.ietf.org/html/rfc6286#section-2.2
+ if (openObj.getBgpIdentifier() != null && openObj.getBgpIdentifier().equals(localPref.getBgpId())) {
+ LOG.warn("Remote and local BGP Identifiers are the same: {}", openObj.getBgpIdentifier());
+ throw new BGPDocumentedException("Remote and local BGP Identifiers are the same.", BGPError.BAD_BGP_ID);
+ }
final List<BgpParameters> prefs = openObj.getBgpParameters();
if (prefs != null && !prefs.isEmpty()) {
import io.netty.channel.Channel;
import io.netty.util.concurrent.Promise;
-
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionValidator;
+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.Open;
protected Ipv4Address getDestinationId(final Open openMsg, final BGPSessionPreferences preferences) {
return openMsg.getBgpIdentifier();
}
+
+ @Override
+ protected AsNumber getAsNumber(Open openMsg, BGPSessionPreferences preferences) {
+ return new AsNumber(openMsg.getMyAsNumber().longValue());
+ }
}
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
import org.opendaylight.protocol.bgp.rib.impl.spi.ReusableBGPPeer;
import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
+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;
@Override
public synchronized BGPSessionListener getPeer(final IpAddress ip,
- final Ipv4Address sourceId, final Ipv4Address remoteId)
+ final Ipv4Address sourceId, final Ipv4Address remoteId, final AsNumber asNumber)
throws BGPDocumentedException {
Preconditions.checkNotNull(ip);
Preconditions.checkNotNull(sourceId);
checkPeerConfigured(ip);
- final BGPSessionId currentConnection = new BGPSessionId(sourceId, remoteId);
+ final BGPSessionId currentConnection = new BGPSessionId(sourceId, remoteId, asNumber);
final BGPSessionListener p = this.peers.get(ip);
final BGPSessionId previousConnection = this.sessionIds.get(ip);
this.peers.get(ip).releaseConnection();
return this.peers.get(ip);
- // Session reestablished with same source bgp id, dropping current as duplicate
+ } else if (previousConnection.hasHigherAsNumber(currentConnection)) {
+ LOG.warn("BGP session with {} {} has to be dropped. Opposite session already present", ip, currentConnection);
+ throw new BGPDocumentedException(
+ String.format("BGP session with %s initiated %s has to be dropped. Opposite session already present",
+ ip, currentConnection),
+ BGPError.CEASE);
+ } else if (currentConnection.hasHigherAsNumber(previousConnection)) {
+ LOG.warn("BGP session with {} {} released. Replaced by opposite session", ip, previousConnection);
+ this.peers.get(ip).releaseConnection();
+ return this.peers.get(ip);
+ // Session reestablished with same source bgp id, dropping current as duplicate
} else {
LOG.warn("BGP session with %s initiated from %s to %s has to be dropped. Same session already present", ip, sourceId, remoteId);
throw new BGPDocumentedException(
private static final class BGPSessionId {
private final Ipv4Address from, to;
+ private final AsNumber asNumber;
- BGPSessionId(final Ipv4Address from, final Ipv4Address to) {
+ BGPSessionId(final Ipv4Address from, final Ipv4Address to, final AsNumber asNumber) {
this.from = Preconditions.checkNotNull(from);
this.to = Preconditions.checkNotNull(to);
+ this.asNumber = Preconditions.checkNotNull(asNumber);
}
/**
return toLong(this.from) > toLong(other.from);
}
+ boolean hasHigherAsNumber(final BGPSessionId other) {
+ return this.asNumber.getValue() > other.asNumber.getValue();
+ }
+
private long toLong(final Ipv4Address from) {
final int i = InetAddresses.coerceToInteger(InetAddresses.forString(from.getValue()));
return UnsignedInts.toLong(i);
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
+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;
* @throws BGPDocumentedException if session establishment cannot be finished successfully
* @throws java.lang.IllegalStateException if there is no peer configured for provided ip address
*/
- BGPSessionListener getPeer(IpAddress ip, Ipv4Address sourceId, Ipv4Address remoteId) throws BGPDocumentedException;
+ BGPSessionListener getPeer(IpAddress ip, Ipv4Address sourceId, Ipv4Address remoteId, AsNumber asNumber) throws BGPDocumentedException;
/**
* @param ip address of remote peer
assertEquals(BGPError.FSM_ERROR.getSubcode(), ((Notify) m).getErrorSubcode().shortValue());
}
+ @Test
+ public void sameBGPIDs() {
+ this.clientSession.channelActive(null);
+ assertEquals(1, this.receivedMsgs.size());
+ assertTrue(this.receivedMsgs.get(0) instanceof Open);
+
+ this.clientSession.handleMessage(new OpenBuilder(this.classicOpen).setBgpIdentifier(new Ipv4Address("1.1.1.1")).build());
+ assertEquals(2, this.receivedMsgs.size());
+ assertTrue(this.receivedMsgs.get(1) instanceof Notify);
+ final Notification m = this.receivedMsgs.get(this.receivedMsgs.size() - 1);
+ assertEquals(BGPError.BAD_BGP_ID, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
+ }
+
@After
public void tearDown() {
import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
import org.opendaylight.protocol.bgp.rib.impl.spi.ReusableBGPPeer;
import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener;
+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;
final Ipv4Address from = new Ipv4Address("0.0.0.1");
final IpAddress remoteIp = new IpAddress(from);
final Ipv4Address to = new Ipv4Address("255.255.255.255");
+ final AsNumber as = new AsNumber(1234L);
final ReusableBGPPeer session1 = getMockSession();
this.droppingBGPSessionRegistry.addPeer(remoteIp, session1, this.mockPreferences);
- this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as);
try {
- this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as);
} catch (final BGPDocumentedException e) {
assertEquals(BGPError.CEASE, e.getError());
return;
final Ipv4Address from = new Ipv4Address("0.0.0.1");
final IpAddress remoteIp = new IpAddress(from);
final Ipv4Address to = new Ipv4Address("255.255.255.255");
+ final AsNumber as = new AsNumber(1234L);
try {
- this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as);
} catch (final IllegalStateException e) {
return;
}
final IpAddress remoteIp = new IpAddress(to);
final Ipv4Address to2 = new Ipv4Address("255.255.255.254");
final IpAddress remoteIp2 = new IpAddress(to2);
+ final AsNumber as = new AsNumber(1234L);
final ReusableBGPPeer session1 = getMockSession();
this.droppingBGPSessionRegistry.addPeer(remoteIp, session1, this.mockPreferences);
final ReusableBGPPeer session2 = getMockSession();
this.droppingBGPSessionRegistry.addPeer(remoteIp2, session2, this.mockPreferences);
- final BGPSessionListener returnedSession1 = this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to);
+ final BGPSessionListener returnedSession1 = this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as);
assertSame(session1, returnedSession1);
- final BGPSessionListener returnedSession2 = this.droppingBGPSessionRegistry.getPeer(remoteIp2, from, to2);
+ final BGPSessionListener returnedSession2 = this.droppingBGPSessionRegistry.getPeer(remoteIp2, from, to2, as);
assertSame(session2, returnedSession2);
Mockito.verifyZeroInteractions(session1);
final Ipv4Address higher = new Ipv4Address("192.168.200.200");
final Ipv4Address lower = new Ipv4Address("10.10.10.10");
final IpAddress remoteIp = new IpAddress(lower);
+ final AsNumber as = new AsNumber(1234L);
final ReusableBGPPeer session1 = getMockSession();
this.droppingBGPSessionRegistry.addPeer(remoteIp, session1, this.mockPreferences);
- this.droppingBGPSessionRegistry.getPeer(remoteIp, higher, lower);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, higher, lower, as);
try {
- this.droppingBGPSessionRegistry.getPeer(remoteIp, lower, higher);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, lower, higher, as);
} catch (final BGPDocumentedException e) {
assertEquals(BGPError.CEASE, e.getError());
return;
final Ipv4Address higher = new Ipv4Address("123.123.123.123");
final Ipv4Address lower = new Ipv4Address("123.123.123.122");
final IpAddress remoteIp = new IpAddress(lower);
+ final AsNumber as = new AsNumber(1234L);
final ReusableBGPPeer session1 = getMockSession();
this.droppingBGPSessionRegistry.addPeer(remoteIp, session1, this.mockPreferences);
- this.droppingBGPSessionRegistry.getPeer(remoteIp, lower, higher);
- this.droppingBGPSessionRegistry.getPeer(remoteIp, higher, lower);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, lower, higher, as);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, higher, lower, as);
Mockito.verify(session1).releaseConnection();
}
final Ipv4Address from = new Ipv4Address("0.0.0.1");
final IpAddress remoteIp = new IpAddress(from);
final Ipv4Address to = new Ipv4Address("255.255.255.255");
+ final AsNumber as = new AsNumber(1234L);
final ReusableBGPPeer session1 = getMockSession();
this.droppingBGPSessionRegistry.addPeer(remoteIp, session1, this.mockPreferences);
- this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as);
try {
- this.droppingBGPSessionRegistry.getPeer(remoteIp, to, to);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, to, to, as);
+ } catch (final BGPDocumentedException e) {
+ assertEquals(BGPError.CEASE, e.getError());
+ return;
+ }
+
+ fail("Same peer cannot be connected twice");
+ }
+
+ @Test
+ public void testDuplicateHigerAs() throws Exception {
+ final Ipv4Address from = new Ipv4Address("0.0.0.1");
+ final IpAddress remoteIp = new IpAddress(from);
+ final Ipv4Address to = new Ipv4Address("255.255.255.255");
+ final AsNumber as1 = new AsNumber(1L);
+ final AsNumber as2 = new AsNumber(3L);
+
+ final ReusableBGPPeer session1 = getMockSession();
+ this.droppingBGPSessionRegistry.addPeer(remoteIp, session1, this.mockPreferences);
+
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as1);
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as2);
+ Mockito.verify(session1).releaseConnection();
+ }
+
+ @Test
+ public void testDuplicateLowerAs() throws Exception {
+ final Ipv4Address from = new Ipv4Address("0.0.0.1");
+ final IpAddress remoteIp = new IpAddress(from);
+ final Ipv4Address to = new Ipv4Address("255.255.255.255");
+ final AsNumber as1 = new AsNumber(10L);
+ final AsNumber as2 = new AsNumber(3L);
+
+ final ReusableBGPPeer session1 = getMockSession();
+ this.droppingBGPSessionRegistry.addPeer(remoteIp, session1, this.mockPreferences);
+
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as1);
+ try {
+ this.droppingBGPSessionRegistry.getPeer(remoteIp, from, to, as2);
} catch (final BGPDocumentedException e) {
assertEquals(BGPError.CEASE, e.getError());
return;
}
@Override
- public BGPSessionListener getPeer(final IpAddress ip, final Ipv4Address sourceId, final Ipv4Address remoteId) throws BGPDocumentedException {
+ public BGPSessionListener getPeer(final IpAddress ip, final Ipv4Address sourceId, final Ipv4Address remoteId, final AsNumber asNumber) throws BGPDocumentedException {
return new SpeakerSessionListener();
}