private final boolean mpSupport;
private final ListenerRegistration<AdjRibOutListener> registerDataTreeChangeListener;
private final LongAdder prefixesSentCounter = new LongAdder();
+ private final TablesKey tablesKey;
+ private boolean initalState;
private AdjRibOutListener(final PeerId peerId, final TablesKey tablesKey, final YangInstanceIdentifier ribId,
final CodecsRegistry registry, final RIBSupport<?, ?, ?, ?> support, final DOMDataTreeChangeService service,
this.support = requireNonNull(support);
this.codecs = registry.getCodecs(this.support);
this.mpSupport = mpSupport;
+ this.tablesKey = requireNonNull(tablesKey);
final YangInstanceIdentifier adjRibOutId = ribId.node(Peer.QNAME).node(IdentifierUtils.domPeerId(peerId))
.node(AdjRibOut.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(tablesKey));
+ /*
+ * After listener registration should always be executed ODTC. Even when empty table is present
+ * in data store. Within this first ODTC execution we should advertise present routes and than
+ * send EOR marker. initialState flag is distinguishing between first ODTC execution and the rest.
+ */
+ this.initalState = true;
this.registerDataTreeChangeListener = service.registerDataTreeChangeListener(
new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, adjRibOutId), this);
}
processSupportedFamilyRoutes(child);
}
}
+ if (initalState) {
+ final Update endOfRib = BgpPeerUtil.createEndOfRib(this.tablesKey);
+ this.session.write(endOfRib);
+ this.initalState = false;
+ }
this.session.flush();
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.destination.ipv4.Ipv4PrefixesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationIpv4CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Update;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.UpdateMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.BgpParameters;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.update.message.Nlri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpAddPathTableType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.RouteRefresh;
} else {
mpUnreach = MessageUtil.getMpUnreachNlri(attrs);
}
- final boolean endOfRib = isEndOfRib(message);
+ final boolean endOfRib = BgpPeerUtil.isEndOfRib(message);
if (mpUnreach != null) {
if (endOfRib) {
final TablesKey tablesKey = new TablesKey(mpUnreach.getAfi(), mpUnreach.getSafi());
.schedule(this::handleSelectionReferralTimer, referalTimerNanos - elapsedNanos, TimeUnit.NANOSECONDS);
}
- private boolean isEndOfRib(final UpdateMessage msg) {
- if (msg.getNlri() == null && msg.getWithdrawnRoutes() == null) {
- final Attributes msgAttributes = msg.getAttributes();
- if (msgAttributes != null) {
- final Attributes2 pa = msgAttributes.augmentation(Attributes2.class);
- if (msgAttributes.augmentation(Attributes1.class) == null && pa != null) {
- //only MP_UNREACH_NLRI allowed in EOR
- if (pa.getMpUnreachNlri() != null && pa.getMpUnreachNlri().getWithdrawnRoutes() == null) {
- // EOR message contains only MPUnreach attribute and no NLRI
- return true;
- }
- }
- } else {
- // true for empty IPv4 Unicast
- return true;
- }
- }
- return false;
- }
-
private void releaseConnectionGracefully() {
if (getPeerRestartTime() > 0) {
setRestartingState();
--- /dev/null
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.rib.impl;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.UpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.UpdateMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.UnicastSubsequentAddressFamily;
+
+public final class BgpPeerUtil {
+
+ private BgpPeerUtil() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Creates UPDATE message that contains EOR marker for specified address family.
+ *
+ * @param key of family for which we need EOR
+ * @return UPDATE message with EOR marker
+ */
+ public static Update createEndOfRib(final TablesKey key) {
+ return key.getAfi() == Ipv4AddressFamily.class && key.getSafi() == UnicastSubsequentAddressFamily.class
+ ? new UpdateBuilder().build() :
+ new UpdateBuilder()
+ .setAttributes(new AttributesBuilder()
+ .addAugmentation(Attributes2.class, new Attributes2Builder()
+ .setMpUnreachNlri(new MpUnreachNlriBuilder()
+ .setAfi(key.getAfi())
+ .setSafi(key.getSafi())
+ .build()).build()).build()).build();
+ }
+
+ /**
+ * Verify presence of EOR marker in UPDATE message.
+ *
+ * @param msg UPDATE message to be checked
+ * @return True if message contains EOR marker, otherwise return False
+ */
+ public static boolean isEndOfRib(final UpdateMessage msg) {
+ if (msg.getNlri() == null && msg.getWithdrawnRoutes() == null) {
+ if (msg.getAttributes() != null) {
+ final Attributes2 pa = msg.getAttributes().augmentation(Attributes2.class);
+ if (pa != null && msg.getAttributes().augmentation(Attributes1.class) == null) {
+ //only MP_UNREACH_NLRI allowed in EOR
+ if (pa.getMpUnreachNlri() != null && pa.getMpUnreachNlri().getWithdrawnRoutes() == null) {
+ // EOR message contains only MPUnreach attribute and no NLRI
+ return true;
+ }
+ }
+ } else {
+ // true for empty IPv4 Unicast
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
BGPSessionImpl createPeerSession(final Ipv4Address peer, final BgpParameters bgpParameters,
final SimpleSessionListener sessionListener) throws InterruptedException {
+ return createPeerSession(peer,bgpParameters, sessionListener, AS_NUMBER);
+ }
+
+ BGPSessionImpl createPeerSession(final Ipv4Address peer, final BgpParameters bgpParameters,
+ final SimpleSessionListener sessionListener,
+ final AsNumber remoteAsNumber) throws InterruptedException {
final StrictBGPPeerRegistry clientRegistry = new StrictBGPPeerRegistry();
final BGPDispatcherImpl clientDispatcher = new BGPDispatcherImpl(this.context.getMessageRegistry(), this.boss,
- this.worker, clientRegistry);
+ this.worker, clientRegistry);
clientRegistry.addPeer(new IpAddress(new Ipv4Address(RIB_ID)), sessionListener,
- new BGPSessionPreferences(AS_NUMBER, HOLDTIMER, new BgpId(peer),
- AS_NUMBER, Lists.newArrayList(bgpParameters)));
+ new BGPSessionPreferences(remoteAsNumber, HOLDTIMER, new BgpId(peer),
+ AS_NUMBER, Lists.newArrayList(bgpParameters)));
return connectPeer(peer, clientDispatcher);
}
//the best route
sendRouteAndCheckIsOnLocRib(session1, PREFIX1, 100, 1);
- checkReceivedMessages(listener4, 1);
- checkReceivedMessages(listener5, 1);
- assertEquals(UPD_100, listener5.getListMsg().get(0));
+ checkReceivedMessages(listener4, 2);
+ checkReceivedMessages(listener5, 2);
+ assertEquals(UPD_100, listener5.getListMsg().get(1));
final BGPPeerState peer1State = peer1.getPeerState();
assertNull(peer1State.getGroupId());
assertEquals(State.UP, peer1State.getBGPSessionState().getSessionState());
checkEquals(()-> assertEquals(1L,
peer1State.getBGPPeerMessagesState().getUpdateMessagesReceivedCount()));
- checkEquals(()-> assertEquals(0L,
+ checkEquals(()-> assertEquals(1L,
peer1State.getBGPPeerMessagesState().getUpdateMessagesSentCount()));
final BGPSessionState sessionStatePeer1 = peer1State.getBGPSessionState();
PeerRole.RrClient, this.serverRegistry);
final BGPSessionImpl session6 = createPeerSession(PEER6, nonAddPathParams, listener6);
checkPeersPresentOnDataStore(6);
- checkReceivedMessages(listener6, 1);
- assertEquals(UPD_NA_100, listener6.getListMsg().get(0));
+ checkReceivedMessages(listener6, 2);
+ assertEquals(UPD_NA_100, listener6.getListMsg().get(1));
causeBGPError(session6);
checkEquals(()-> assertEquals(1L,
peer6.getPeerState().getBGPPeerMessagesState().getNotificationMessagesSentCount()));
//the second best route
sendRouteAndCheckIsOnLocRib(session2, PREFIX1, 50, 2);
- checkReceivedMessages(listener4, 1);
- checkReceivedMessages(listener5, 2);
- assertEquals(UPD_50, listener5.getListMsg().get(1));
+ checkReceivedMessages(listener4, 2);
+ checkReceivedMessages(listener5, 3);
+ assertEquals(UPD_50, listener5.getListMsg().get(2));
//new best route
sendRouteAndCheckIsOnLocRib(session3, PREFIX1, 200, 3);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 3);
- assertEquals(UPD_200, listener5.getListMsg().get(2));
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 4);
+ assertEquals(UPD_200, listener5.getListMsg().get(3));
peer4State = peer4.getPeerState();
assertNull(peer4State.getGroupId());
assertEquals(0L, peerMessagesState.getNotificationMessagesReceivedCount());
assertEquals(0L, peerMessagesState.getNotificationMessagesSentCount());
assertEquals(0L, peerMessagesState.getUpdateMessagesReceivedCount());
- assertEquals(2L, peerMessagesState.getUpdateMessagesSentCount());
+ assertEquals(3L, peerMessagesState.getUpdateMessagesSentCount());
final BGPSessionState bgpSessionState = peer4State.getBGPSessionState();
assertEquals(State.UP, bgpSessionState.getSessionState());
//the worst route
sendRouteAndCheckIsOnLocRib(session1, PREFIX1, 20, 3);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 4);
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 5);
assertEquals(UPD_200.getAttributes().getLocalPref(),
- ((Update) listener4.getListMsg().get(1)).getAttributes().getLocalPref());
- assertEquals(UPD_20, listener5.getListMsg().get(3));
+ ((Update) listener4.getListMsg().get(2)).getAttributes().getLocalPref());
+ assertEquals(UPD_20, listener5.getListMsg().get(4));
//withdraw second best route, 1 advertisement(1 withdrawal) for add-path supported, none for non add path
sendWithdrawalRouteAndCheckIsOnLocRib(session1, PREFIX1, 100, 2);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 5);
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 6);
//we advertise again to try new test
sendRouteAndCheckIsOnLocRib(session1, PREFIX1, 100, 3);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 6);
- assertEquals(UPD_200, listener5.getListMsg().get(2));
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 7);
+ assertEquals(UPD_200, listener5.getListMsg().get(3));
//withdraw second best route, 1 advertisement(1 withdrawal) for add-path supported, 1 for non add path (withdrawal)
sendWithdrawalRouteAndCheckIsOnLocRib(session3, PREFIX1, 200, 2);
- checkReceivedMessages(listener4, 3);
- checkReceivedMessages(listener5, 7);
+ checkReceivedMessages(listener4, 4);
+ checkReceivedMessages(listener5, 8);
sendNotification(session1);
checkEquals(()-> assertEquals(1L,
//new best route so far
sendRouteAndCheckIsOnLocRib(session1, PREFIX1, 100, 1);
- checkReceivedMessages(listener4, 1);
- checkReceivedMessages(listener5, 1);
- assertEquals(UPD_NA_100, listener4.getListMsg().get(0));
- assertEquals(UPD_NA_100_EBGP, listener5.getListMsg().get(0));
+ checkReceivedMessages(listener4, 2);
+ checkReceivedMessages(listener5, 2);
+ assertEquals(UPD_NA_100, listener4.getListMsg().get(1));
+ assertEquals(UPD_NA_100_EBGP, listener5.getListMsg().get(1));
//the second best route
sendRouteAndCheckIsOnLocRib(session2, PREFIX1, 100, 1);
- checkReceivedMessages(listener4, 1);
- checkReceivedMessages(listener5, 1);
+ checkReceivedMessages(listener4, 2);
+ checkReceivedMessages(listener5, 2);
//new best route
sendRouteAndCheckIsOnLocRib(session3, PREFIX1, 200, 1);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 2);
- assertEquals(UPD_NA_200, listener4.getListMsg().get(1));
- assertEquals(UPD_NA_200_EBGP, listener5.getListMsg().get(1));
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 3);
+ assertEquals(UPD_NA_200, listener4.getListMsg().get(2));
+ assertEquals(UPD_NA_200_EBGP, listener5.getListMsg().get(2));
final SimpleSessionListener listener6 = new SimpleSessionListener();
configurePeer(this.tableRegistry, PEER6, this.ribImpl, nonAddPathParams, PeerRole.RrClient,
final BGPSessionImpl session6 = createPeerSession(PEER6, nonAddPathParams, listener6);
checkPeersPresentOnDataStore(6);
- checkReceivedMessages(listener6, 1);
- assertEquals(UPD_NA_200, listener6.getListMsg().get(0));
+ checkReceivedMessages(listener6, 2);
+ assertEquals(UPD_NA_200, listener6.getListMsg().get(1));
session6.close();
checkPeersPresentOnDataStore(5);
//best route updated to be the worse one
sendRouteAndCheckIsOnLocRib(session3, PREFIX1, 20, 1);
- checkReceivedMessages(listener4, 3);
- checkReceivedMessages(listener5, 3);
- assertEquals(UPD_NA_100, listener4.getListMsg().get(2));
- assertEquals(UPD_NA_100_EBGP, listener5.getListMsg().get(2));
+ checkReceivedMessages(listener4, 4);
+ checkReceivedMessages(listener5, 4);
+ assertEquals(UPD_NA_100, listener4.getListMsg().get(3));
+ assertEquals(UPD_NA_100_EBGP, listener5.getListMsg().get(3));
//Remove second best, no advertisement should be done
sendWithdrawalRouteAndCheckIsOnLocRib(session2, PREFIX1, 50, 1);
- checkReceivedMessages(listener4, 3);
- checkReceivedMessages(listener5, 3);
+ checkReceivedMessages(listener4, 4);
+ checkReceivedMessages(listener5, 4);
//Remove best, 1 advertisement
sendWithdrawalRouteAndCheckIsOnLocRib(session1, PREFIX1, 100, 1);
- checkReceivedMessages(listener4, 4);
- checkReceivedMessages(listener5, 4);
+ checkReceivedMessages(listener4, 5);
+ checkReceivedMessages(listener5, 5);
//Remove best, 1 withdrawal
sendWithdrawalRouteAndCheckIsOnLocRib(session3, PREFIX1, 20, 0);
- checkReceivedMessages(listener4, 5);
- checkReceivedMessages(listener5, 5);
+ checkReceivedMessages(listener4, 6);
+ checkReceivedMessages(listener5, 6);
session1.close();
session2.close();
//new best route so far
sendRouteAndCheckIsOnLocRib(session1, PREFIX1, 100, 1);
- checkReceivedMessages(listener4, 1);
- checkReceivedMessages(listener5, 1);
- assertEquals(UPD_100, listener5.getListMsg().get(0));
+ checkReceivedMessages(listener4, 2);
+ checkReceivedMessages(listener5, 2);
+ assertEquals(UPD_100, listener5.getListMsg().get(1));
final SimpleSessionListener listener6 = new SimpleSessionListener();
configurePeer(this.tableRegistry, PEER6, this.ribImpl, nonAddPathParams, PeerRole.RrClient,
this.serverRegistry);
final BGPSessionImpl session6 = createPeerSession(PEER6, nonAddPathParams, listener6);
checkPeersPresentOnDataStore(6);
- checkReceivedMessages(listener6, 1);
- assertEquals(UPD_NA_100, listener6.getListMsg().get(0));
+ checkReceivedMessages(listener6, 2);
+ assertEquals(UPD_NA_100, listener6.getListMsg().get(1));
session6.close();
checkPeersPresentOnDataStore(5);
//the second best route
sendRouteAndCheckIsOnLocRib(session2, PREFIX1, 50, 2);
- checkReceivedMessages(listener4, 1);
- checkReceivedMessages(listener5, 2);
- assertEquals(UPD_50, listener5.getListMsg().get(1));
+ checkReceivedMessages(listener4, 2);
+ checkReceivedMessages(listener5, 3);
+ assertEquals(UPD_50, listener5.getListMsg().get(2));
//new best route
sendRouteAndCheckIsOnLocRib(session3, PREFIX1, 200, 2);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 3);
- assertEquals(UPD_200, listener5.getListMsg().get(2));
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 4);
+ assertEquals(UPD_200, listener5.getListMsg().get(3));
//the worst prefix, no changes
sendRouteAndCheckIsOnLocRib(session2, PREFIX1, 20, 2);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 3);
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 4);
//withdraw second best route, 2 advertisement (1 withdrawal) for add-path supported, none for non add path
sendWithdrawalRouteAndCheckIsOnLocRib(session1, PREFIX1, 100, 2);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 5);
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 6);
//we advertise again to try new test
sendRouteAndCheckIsOnLocRib(session1, PREFIX1, 100, 2);
- checkReceivedMessages(listener4, 2);
- checkReceivedMessages(listener5, 6);
+ checkReceivedMessages(listener4, 3);
+ checkReceivedMessages(listener5, 7);
//withdraw second best route, 2 advertisement (1 withdrawal) for add-path supported,
// 1 withdrawal for non add path
sendWithdrawalRouteAndCheckIsOnLocRib(session3, PREFIX1, 200, 2);
- checkReceivedMessages(listener4, 3);
- checkReceivedMessages(listener5, 8);
+ checkReceivedMessages(listener4, 4);
+ checkReceivedMessages(listener5, 9);
session1.close();
session2.close();
--- /dev/null
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.rib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.UpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.UnicastSubsequentAddressFamily;
+
+public class BgpPeerUtilTest {
+
+ private final TablesKey IPV4_TABLE_KEY = new TablesKey(Ipv4AddressFamily.class,
+ UnicastSubsequentAddressFamily.class);
+ private final TablesKey IPV6_TABLE_KEY = new TablesKey(Ipv6AddressFamily.class,
+ UnicastSubsequentAddressFamily.class);
+
+ @Test
+ public void createIpv4EORTest() {
+ final Update endOfRib = BgpPeerUtil.createEndOfRib(IPV4_TABLE_KEY);
+ assertNull(endOfRib.getNlri());
+ assertNull(endOfRib.getWithdrawnRoutes());
+ assertNull(endOfRib.getAttributes());
+ }
+
+ @Test
+ public void createNonIpv4EORTest() {
+ final Update endOfRib = BgpPeerUtil.createEndOfRib(IPV6_TABLE_KEY);
+ assertNull(endOfRib.getNlri());
+ assertNull(endOfRib.getWithdrawnRoutes());
+ final Attributes attributes = endOfRib.getAttributes();
+ assertNotNull(attributes);
+ final Attributes2 augmentation = attributes.augmentation(Attributes2.class);
+ assertNotNull(augmentation);
+ final MpUnreachNlri mpUnreachNlri = augmentation.getMpUnreachNlri();
+ assertNotNull(mpUnreachNlri);
+ assertEquals(IPV6_TABLE_KEY.getAfi(), mpUnreachNlri.getAfi());
+ assertEquals(IPV6_TABLE_KEY.getSafi(), mpUnreachNlri.getSafi());
+ assertNull(mpUnreachNlri.getWithdrawnRoutes());
+ }
+
+ @Test
+ public void isEndOfTableTest() {
+ final Update ipv4EOT = new UpdateBuilder().build();
+ final MpUnreachNlri ipv6EOTnlri = new MpUnreachNlriBuilder()
+ .setAfi(IPV6_TABLE_KEY.getAfi())
+ .setSafi(IPV6_TABLE_KEY.getSafi())
+ .build();
+ final Update ipv6EOT = new UpdateBuilder()
+ .setAttributes(new AttributesBuilder()
+ .addAugmentation(Attributes2.class, new Attributes2Builder()
+ .setMpUnreachNlri(ipv6EOTnlri)
+ .build())
+ .build())
+ .build();
+
+ assertTrue(BgpPeerUtil.isEndOfRib(ipv4EOT));
+ assertTrue(BgpPeerUtil.isEndOfRib(ipv6EOT));
+
+ final Update ipv4NonEOT = new UpdateBuilder()
+ .setNlri(Collections.emptyList())
+ .build();
+ final MpUnreachNlri ipv6NonEOTnlri = new MpUnreachNlriBuilder(ipv6EOTnlri)
+ .setWithdrawnRoutes(new WithdrawnRoutesBuilder().build())
+ .build();
+ final Update ipv6NonEOT = new UpdateBuilder()
+ .setAttributes(new AttributesBuilder()
+ .addAugmentation(Attributes2.class, new Attributes2Builder()
+ .setMpUnreachNlri(ipv6NonEOTnlri)
+ .build())
+ .build())
+ .build();
+
+ assertFalse(BgpPeerUtil.isEndOfRib(ipv4NonEOT));
+ assertFalse(BgpPeerUtil.isEndOfRib(ipv6NonEOT));
+ }
+}
*/
package org.opendaylight.protocol.bgp.rib.impl;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.opendaylight.protocol.bgp.rib.impl.CheckUtil.checkIdleState;
import static org.opendaylight.protocol.bgp.rib.impl.CheckUtil.checkStateIsNotRestarting;
import static org.opendaylight.protocol.bgp.rib.impl.CheckUtil.checkUpState;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.UnicastSubsequentAddressFamily;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
public class GracefulRestartTest extends AbstractAddPathTest {
private BGPSessionImpl session;
- private BGPSessionImpl session2;
private BGPPeer peer;
- private BgpPeer bgpPeer;
- private BgpParameters parameters;
private final Set<TablesKey> afiSafiAdvertised = new HashSet<>();
private final Set<TablesKey> gracefulAfiSafiAdvertised = new HashSet<>();
private RIBImpl ribImpl;
private Channel serverChannel;
private SimpleSessionListener listener = new SimpleSessionListener();
- private SimpleSessionListener listener2 = new SimpleSessionListener();
+ private final BgpParameters parameters = createParameter(false, true, Collections.singletonMap(TABLES_KEY, true));
private static final int DEFERRAL_TIMER = 5;
private static final RibId RIBID = new RibId("test-rib");
private final Ipv4Prefix PREFIX2 = new Ipv4Prefix("2.2.2.2/32");
waitFutureSuccess(channelFuture);
this.serverChannel = channelFuture.channel();
- gracefulAfiSafiAdvertised.add(new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
- afiSafiAdvertised.addAll(gracefulAfiSafiAdvertised);
+ gracefulAfiSafiAdvertised.add(TABLES_KEY);
+ afiSafiAdvertised.add(TABLES_KEY);
afiSafiAdvertised.add(IPV6_TABLES_KEY);
- this.parameters = createParameter(false, true, Collections.singletonMap(TABLES_KEY, true));
- this.bgpPeer = Mockito.mock(BgpPeer.class);
- Mockito.doReturn(GRACEFUL_RESTART_TIME).when(this.bgpPeer).getGracefulRestartTimer();
+ final BgpPeer bgpPeer = Mockito.mock(BgpPeer.class);
+ Mockito.doReturn(GRACEFUL_RESTART_TIME).when(bgpPeer).getGracefulRestartTimer();
Mockito.doReturn(createParameter(false, true, Collections.singletonMap(TABLES_KEY, false))
- .getOptionalCapabilities()).when(this.bgpPeer).getBgpFixedCapabilities();
+ .getOptionalCapabilities()).when(bgpPeer).getBgpFixedCapabilities();
this.peer = configurePeer(this.tableRegistry, PEER1, this.ribImpl, parameters, PeerRole.Ibgp,
this.serverRegistry, afiSafiAdvertised, gracefulAfiSafiAdvertised, bgpPeer);
this.session = createPeerSession(PEER1, parameters, this.listener);
- final BgpParameters parameters2 = createParameter(false, true, Collections.singletonMap(TABLES_KEY, true));
- configurePeer(this.tableRegistry, PEER2, this.ribImpl, parameters2, PeerRole.Ibgp,
- this.serverRegistry, afiSafiAdvertised, gracefulAfiSafiAdvertised);
- this.session2 = createPeerSession(PEER2, parameters2, this.listener2);
}
@After
final Open open = createClassicOpen(true);
this.session.writeAndFlush(open);
checkIdleState(this.peer);
- checkReceivedMessages(this.listener, 0);
+ checkReceivedMessages(this.listener, 2);
}
/**
public void retainRoutesOnPeerRestartTest() throws Exception {
final List<Ipv4Prefix> ipv4Prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1), new Ipv4Prefix(PREFIX2));
final List<Ipv6Prefix> ipv6Prefixes = Collections.singletonList(new Ipv6Prefix(PREFIX3));
- insertRoutes(ipv4Prefixes, PEER1, ipv6Prefixes, IPV6_NEXT_HOP, this.session);
+ insertRoutes(ipv4Prefixes, ipv6Prefixes);
checkLocRibIpv4Routes(2);
checkLocRibIpv6Routes(1);
@Test
public void removeRoutesOnMissingGracefulRestartAfiSafiTest() throws Exception {
retainRoutesOnPeerRestartTest();
- this.session = createPeerSession(PEER1, createParameter(false, true, Collections.singletonMap(TABLES_KEY, false)),
- this.listener);
+ this.session = createPeerSession(PEER1, createParameter(false, true,
+ Collections.singletonMap(TABLES_KEY, false)), this.listener);
checkUpState(listener);
checkUpState(this.peer);
checkLocRibIpv4Routes(0);
this.session = createPeerSession(PEER1, createParameter(false, true,
Collections.singletonMap(TABLES_KEY, true)), this.listener);
checkUpState(this.listener);
- insertRoutes(Collections.singletonList(new Ipv4Prefix(PREFIX1)), PEER1, null, null, this.session);
- insertRoutes(null, null, null, null, this.session);
+ final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
+ insertRoutes(ipv4prefixes, null);
+ insertRoutes(null, null);
checkLocRibIpv4Routes(1);
checkLocRibIpv6Routes(0);
}
*/
@Test
public void performLocalGracefulRestart() throws Exception {
- final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
- final List<Ipv4Prefix> ipv4prefixes2 = Arrays.asList(new Ipv4Prefix(PREFIX2));
+ final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1), new Ipv4Prefix(PREFIX2));
final List<Ipv6Prefix> ipv6prefixes = Arrays.asList(new Ipv6Prefix(PREFIX3));
- insertRoutes(ipv4prefixes, PEER1, ipv6prefixes, IPV6_NEXT_HOP, this.session);
- insertRoutes(ipv4prefixes2, PEER2, null, null, this.session2);
+ insertRoutes(ipv4prefixes, ipv6prefixes);
checkLocRibIpv4Routes(2);
checkLocRibIpv6Routes(1);
performLocalGracefulRestart();
final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
final List<Ipv6Prefix> ipv6prefixes = Arrays.asList(new Ipv6Prefix(PREFIX3));
- insertRoutes(ipv4prefixes, PEER1, ipv6prefixes, IPV6_NEXT_HOP, this.session);
+ insertRoutes(ipv4prefixes, ipv6prefixes);
checkLocRibIpv4Routes(2);
checkLocRibIpv6Routes(0);
- insertRoutes(null, null,null, null, this.session);
+ insertRoutes(null, null);
checkLocRibIpv4Routes(2);
checkLocRibIpv6Routes(1);
}
performLocalGracefulRestart();
final List<Ipv4Prefix> ipv4prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
final List<Ipv6Prefix> ipv6prefixes = Arrays.asList(new Ipv6Prefix(PREFIX3));
- insertRoutes(ipv4prefixes, PEER1, ipv6prefixes, IPV6_NEXT_HOP, this.session);
+ insertRoutes(ipv4prefixes, ipv6prefixes);
checkLocRibIpv4Routes(2);
checkLocRibIpv6Routes(0);
checkStateIsNotRestarting(this.peer, DEFERRAL_TIMER);
checkLocRibIpv6Routes(1);
}
+ /**
+ * After graceful restart is performed from peer side we have to re-advertise routes followed by
+ * End-of-RIB marker.
+ *
+ * @throws Exception on reading Rib failure
+ */
+ @Test
+ public void verifySendEORafterRestartTest() throws Exception {
+ final SimpleSessionListener listener2 = new SimpleSessionListener();
+ configurePeer(this.tableRegistry, PEER2, this.ribImpl, this.parameters, PeerRole.Ebgp,
+ this.serverRegistry, afiSafiAdvertised, gracefulAfiSafiAdvertised);
+ final BGPSessionImpl session2 = createPeerSession(PEER2, this.parameters, listener2);
+ final List<Ipv4Prefix> ipv4Prefixes = Arrays.asList(new Ipv4Prefix(PREFIX1));
+ final List<Ipv4Prefix> ipv4Prefixes2 = Arrays.asList(new Ipv4Prefix(PREFIX2));
+ final List<Ipv6Prefix> ipv6Prefixes = Collections.singletonList(new Ipv6Prefix(PREFIX3));
+ insertRoutes(ipv4Prefixes, ipv6Prefixes);
+ insertRoutes(ipv4Prefixes2, PEER2, null, null, session2, BgpOrigin.Egp);
+ checkLocRibIpv4Routes(2);
+ checkLocRibIpv6Routes(1);
+ org.opendaylight.protocol.util.CheckUtil.checkReceivedMessages(this.listener, 3);
+ // verify sending of Ipv4 EOT, Ipv6 EOT and Ipv4 update with route
+ checkReceivedMessages(this.listener, 3);
+ assertTrue(this.listener.getListMsg().get(0) instanceof Update);
+ assertTrue(BgpPeerUtil.isEndOfRib((Update)this.listener.getListMsg().get(0)));
+ assertTrue(this.listener.getListMsg().get(1) instanceof Update);
+ assertTrue(BgpPeerUtil.isEndOfRib((Update)this.listener.getListMsg().get(1)));
+ assertTrue(this.listener.getListMsg().get(2) instanceof Update);
+ assertFalse(BgpPeerUtil.isEndOfRib((Update)this.listener.getListMsg().get(2)));
+
+ this.session.close();
+ checkIdleState(this.peer);
+ checkLocRibIpv4Routes(2);
+ checkLocRibIpv6Routes(0);
+ // verify nothing new was sent
+ checkReceivedMessages(this.listener, 3);
+
+ this.session = createPeerSession(PEER1, createParameter(false, true,
+ Collections.singletonMap(TABLES_KEY, true)), this.listener);
+ checkUpState(listener);
+ checkUpState(this.peer);
+ org.opendaylight.protocol.util.CheckUtil.checkReceivedMessages(this.listener, 6);
+ // verify sending of Ipv4 update with route, Ipv4 EOT and Ipv6 EOT; order can vary based on ODTC order
+ final List<Notification> subList = this.listener.getListMsg().subList(3, 6);
+ int EOTCount = 0;
+ int routeUpdateCount = 0;
+ for (Notification message : subList) {
+ if (BgpPeerUtil.isEndOfRib((Update) message)) {
+ EOTCount++;
+ } else {
+ routeUpdateCount++;
+ }
+ }
+ assertEquals(2, EOTCount);
+ assertEquals(1, routeUpdateCount);
+ }
+
private void checkLocRibIpv4Routes(final int expectedRoutesOnDS) throws Exception {
readDataOperational(getDataBroker(), IPV4_IID, table -> {
int size = 0;
routesCase.getIpv4Routes().getIpv4Route() != null) {
size = routesCase.getIpv4Routes().getIpv4Route().size();
}
- Assert.assertEquals(expectedRoutesOnDS, size);
+ assertEquals(expectedRoutesOnDS, size);
return table;
});
}
routesCase.getIpv6Routes().getIpv6Route() != null) {
size = routesCase.getIpv6Routes().getIpv6Route().size();
}
- Assert.assertEquals(expectedRoutesOnDS, size);
+ assertEquals(expectedRoutesOnDS, size);
return table;
});
}
- private void insertRoutes(List<Ipv4Prefix> ipv4prefixes, Ipv4Address ipv4NextHop, List<Ipv6Prefix> ipv6prefixes,
- Ipv6Address ipv6NextHop, BGPSessionImpl session) {
+ private void insertRoutes(List<Ipv4Prefix> ipv4prefixes, List<Ipv6Prefix> ipv6prefixes) {
+ insertRoutes(ipv4prefixes, PEER1, ipv6prefixes, IPV6_NEXT_HOP, this.session, BgpOrigin.Igp);
+ }
+
+ private void insertRoutes(final List<Ipv4Prefix> ipv4prefixes, final Ipv4Address ipv4NeighborAddress,
+ final List<Ipv6Prefix> ipv6prefixes, final Ipv6Address ipv6NeighborAddress,
+ final BGPSessionImpl session, final BgpOrigin peerRole) {
if (ipv4prefixes == null && ipv6prefixes == null) {
- waitFutureSuccess(session.writeAndFlush(PeerUtil.createEndOfRib(TABLES_KEY)));
- waitFutureSuccess(session.writeAndFlush(PeerUtil.createEndOfRib(IPV6_TABLES_KEY)));
+ waitFutureSuccess(session.writeAndFlush(BgpPeerUtil.createEndOfRib(TABLES_KEY)));
+ waitFutureSuccess(session.writeAndFlush(BgpPeerUtil.createEndOfRib(IPV6_TABLES_KEY)));
return;
}
if (ipv4prefixes != null && !ipv4prefixes.isEmpty()) {
- final MpReachNlri reachIpv4 = PeerUtil.createMpReachNlri(new IpAddress(ipv4NextHop), 0,
+ final MpReachNlri reachIpv4 = PeerUtil.createMpReachNlri(new IpAddress(ipv4NeighborAddress), 0,
ipv4prefixes.stream()
.map(IpPrefix::new)
.collect(Collectors.toList()));
- final Update update1 = PeerUtil.createUpdate(BgpOrigin.Igp, Collections.emptyList(), 100, reachIpv4, null);
+ final Update update1 = PeerUtil.createUpdate(peerRole, Collections.emptyList(), 100, reachIpv4, null);
waitFutureSuccess(session.writeAndFlush(update1));
}
if (ipv6prefixes != null && !ipv4prefixes.isEmpty()) {
- final MpReachNlri reachIpv6 = PeerUtil.createMpReachNlri(new IpAddress(ipv6NextHop), 0,
+ final MpReachNlri reachIpv6 = PeerUtil.createMpReachNlri(new IpAddress(ipv6NeighborAddress), 0,
ipv6prefixes.stream()
.map(IpPrefix::new)
.collect(Collectors.toList()));
- final Update update2 = PeerUtil.createUpdate(BgpOrigin.Igp, Collections.emptyList(), 100, reachIpv6, null);
+ final Update update2 = PeerUtil.createUpdate(peerRole, Collections.emptyList(), 100, reachIpv6, null);
waitFutureSuccess(session.writeAndFlush(update2));
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpReachNlri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpReachNlriBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlriBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AddressFamily;
.build()).build();
}
- static Update createEndOfRib(final TablesKey key) {
- return key.getAfi() == Ipv4AddressFamily.class ? new UpdateBuilder().build() :
- new UpdateBuilder()
- .setAttributes(new AttributesBuilder()
- .addAugmentation(Attributes2.class, new Attributes2Builder()
- .setMpUnreachNlri(new MpUnreachNlriBuilder()
- .setAfi(key.getAfi())
- .setSafi(key.getSafi())
- .build()).build()).build()).build();
- }
-
static BgpParameters createBgpParameters(final List<TablesKey> advertisedTables,
final List<TablesKey> addPathTables,
final Map<TablesKey, Boolean> gracefulTabes,