2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.protocol.bgp.mode.impl;
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Matchers.eq;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16 import static org.opendaylight.protocol.bgp.mode.impl.base.BasePathSelectorTest.ATTRS_EXTENSION_Q;
17 import static org.opendaylight.protocol.bgp.mode.impl.base.BasePathSelectorTest.SEGMENTS_NID;
19 import com.google.common.collect.ImmutableMap;
20 import com.google.common.primitives.UnsignedInteger;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
25 import java.util.function.BiConsumer;
26 import org.mockito.Mock;
27 import org.mockito.MockitoAnnotations;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
30 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
31 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup;
32 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup.PeerExporTuple;
33 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
34 import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.Ipv4Routes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.ipv4.routes.Ipv4Route;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AtomicAggregate;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.BgpRib;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRib;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibOut;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Routes;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
51 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
52 import org.opendaylight.yangtools.yang.common.QName;
53 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
54 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
55 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
56 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
57 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
58 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
59 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
60 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
62 public abstract class AbstractRouteEntryTest {
63 protected static final long REMOTE_PATH_ID = 1;
64 protected static final PeerId PEER_ID = new PeerId("bgp://42.42.42.42");
65 protected static final YangInstanceIdentifier PEER_YII2 = YangInstanceIdentifier.of(QName.create("urn:opendaylight:params:xml:ns:yang:bgp-inet:test", "2015-03-05", "peer2"));
66 protected static final long AS = 64444;
67 protected static final UnsignedInteger ROUTER_ID = UnsignedInteger.ONE;
68 protected static final TablesKey TABLES_KEY = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
69 protected static final YangInstanceIdentifier LOC_RIB_TARGET = YangInstanceIdentifier.create(YangInstanceIdentifier.of(BgpRib.QNAME)
70 .node(LocRib.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(TABLES_KEY)).getPathArguments());
71 private static final long PATH_ID = 1;
72 private static final PeerId PEER_ID2 = new PeerId("bgp://43.43.43.43");
73 private static final String PREFIX = "1.2.3.4/32";
74 private static final String PREFIX2 = "2.2.2.2/32";
75 private static final YangInstanceIdentifier PEER_YII = YangInstanceIdentifier.of(QName.create("urn:opendaylight:params:xml:ns:yang:bgp-inet:test", "2015-03-05", "peer1"));
76 private static final NodeIdentifier ROUTES_IDENTIFIER = new NodeIdentifier(Routes.QNAME);
77 private static final NodeIdentifier ORIGIN_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, Origin.QNAME.getLocalName()).intern());
78 private static final NodeIdentifier ORIGIN_VALUE_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, "value").intern());
79 private static final NodeIdentifier AS_PATH_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, AsPath.QNAME.getLocalName()).intern());
80 private static final NodeIdentifier ATOMIC_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, AtomicAggregate.QNAME.getLocalName()));
81 private static final QName Q_NAME = BindingReflections.findQName(Ipv4Routes.class).intern();
82 private static final NodeIdentifier ROUTE_ATTRIBUTES_IDENTIFIER = new NodeIdentifier(QName.create(Q_NAME, Attributes.QNAME.getLocalName().intern()));
83 private static final QName PREFIX_QNAME = QName.create(Ipv4Route.QNAME, "prefix").intern();
84 protected static final NodeIdentifierWithPredicates ROUTE_ID_PA = new NodeIdentifierWithPredicates(Ipv4Route.QNAME, ImmutableMap.of(PREFIX_QNAME, PREFIX));
85 private static final QName PATHID_QNAME = QName.create(Ipv4Route.QNAME, "path-id").intern();
86 protected static final NodeIdentifierWithPredicates ROUTE_ID_PA_ADD_PATH = new NodeIdentifierWithPredicates(Ipv4Route.QNAME, ImmutableMap.of(PATHID_QNAME, PATH_ID, PREFIX_QNAME, PREFIX2));
88 protected RIBSupport ribSupport;
90 protected DOMDataWriteTransaction tx;
92 protected ExportPolicyPeerTracker peerPT;
94 protected PeerExportGroup peg;
95 protected List<YangInstanceIdentifier> yIIChanges;
96 protected NormalizedNode<?, ?> attributes;
97 protected YangInstanceIdentifier routePaYii;
98 protected YangInstanceIdentifier routePaAddPathYii;
99 protected YangInstanceIdentifier routeRiboutYii;
100 protected YangInstanceIdentifier routeAddRiboutYii;
101 protected YangInstanceIdentifier routeRiboutAttYii;
102 protected YangInstanceIdentifier routeAddRiboutAttYii;
103 protected YangInstanceIdentifier routeRiboutAttYiiPeer2;
104 protected YangInstanceIdentifier routeRiboutYiiPeer2;
105 protected YangInstanceIdentifier routeAddRiboutYiiPeer2;
107 private PeerExportGroup pegNot;
108 private YangInstanceIdentifier locRibTargetYii;
109 private YangInstanceIdentifier locRibOutTargetYii;
110 private YangInstanceIdentifier locRibOutTargetYiiPeer2;
112 protected void setUp() {
113 MockitoAnnotations.initMocks(this);
114 this.yIIChanges = new ArrayList<>();
115 this.peerPT = mock(ExportPolicyPeerTracker.class);
116 this.attributes = createAttr();
117 this.locRibTargetYii = LOC_RIB_TARGET.node(ROUTES_IDENTIFIER);
118 this.locRibOutTargetYii = PEER_YII.node(AdjRibOut.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(TABLES_KEY)).node(ROUTES_IDENTIFIER);
119 this.routePaYii = this.locRibTargetYii.node(ROUTE_ID_PA);
120 this.routePaAddPathYii = this.locRibTargetYii.node(ROUTE_ID_PA_ADD_PATH);
121 this.routeRiboutYii = this.locRibOutTargetYii.node(ROUTE_ID_PA);
122 this.routeAddRiboutYii = this.locRibOutTargetYii.node(ROUTE_ID_PA_ADD_PATH);
123 this.routeRiboutAttYii = this.locRibOutTargetYii.node(ROUTE_ID_PA).node(ATTRS_EXTENSION_Q);
124 this.routeAddRiboutAttYii = this.locRibOutTargetYii.node(ROUTE_ID_PA_ADD_PATH).node(ATTRS_EXTENSION_Q);
125 this.locRibOutTargetYiiPeer2 = PEER_YII2.node(AdjRibOut.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(TABLES_KEY)).node(ROUTES_IDENTIFIER);
126 this.routeRiboutYiiPeer2 = this.locRibOutTargetYiiPeer2.node(ROUTE_ID_PA);
127 this.routeRiboutAttYiiPeer2 = this.locRibOutTargetYiiPeer2.node(ROUTE_ID_PA).node(ATTRS_EXTENSION_Q);
128 this.routeAddRiboutYiiPeer2 = this.locRibOutTargetYiiPeer2.node(ROUTE_ID_PA_ADD_PATH);
130 mockExportPolicies();
132 mockTransactionChain();
135 private void mockTransactionChain() {
136 doAnswer(invocation -> {
137 final Object[] args = invocation.getArguments();
138 this.yIIChanges.add((YangInstanceIdentifier) args[1]);
140 }).when(this.tx).put(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class), any(NormalizedNode.class));
142 doAnswer(invocation -> {
143 final Object[] args = invocation.getArguments();
144 if (this.routePaYii.equals(args[1])) {
145 this.yIIChanges.remove(this.routePaYii);
146 } else if (this.routePaAddPathYii.equals(args[1])) {
147 this.yIIChanges.remove(this.routePaAddPathYii);
148 } else if (this.routeRiboutYii.equals(args[1])) {
149 this.yIIChanges.remove(this.routeRiboutYii);
150 this.yIIChanges.remove(this.routeAddRiboutAttYii);
151 } else if (this.routeAddRiboutYii.equals(args[1])) {
152 this.yIIChanges.remove(this.routeAddRiboutYii);
153 this.yIIChanges.remove(this.routeAddRiboutAttYii);
156 }).when(this.tx).delete(any(LogicalDatastoreType.class), any(YangInstanceIdentifier.class));
159 private void mockExportGroup() {
160 doReturn(this.attributes).when(this.peg).effectiveAttributes(any(PeerRole.class), any(ContainerNode.class));
161 doReturn(null).when(this.pegNot).effectiveAttributes(any(PeerRole.class), any(ContainerNode.class));
163 final Map<PeerId, PeerExportGroup.PeerExporTuple> peers = new HashMap<>();
164 doAnswer(invocation -> {
165 final BiConsumer action = (BiConsumer) invocation.getArguments()[0];
166 for (final Map.Entry<PeerId, PeerExporTuple> pid : peers.entrySet()) {
167 action.accept(pid.getKey(), pid.getValue().getYii());
170 }).when(this.pegNot).forEach(any());
171 doReturn(true).when(this.pegNot).containsPeer(any(PeerId.class));
173 peers.put(PEER_ID, new PeerExportGroup.PeerExporTuple(PEER_YII, PeerRole.Ibgp));
174 peers.put(PEER_ID2, new PeerExportGroup.PeerExporTuple(PEER_YII2, PeerRole.Ibgp));
175 doAnswer(invocation -> {
176 final BiConsumer action = (BiConsumer) invocation.getArguments()[0];
177 for (final Map.Entry<PeerId, PeerExporTuple> pid : peers.entrySet()) {
178 action.accept(pid.getKey(), pid.getValue().getYii());
181 }).when(this.peg).forEach(any());
184 private void mockExportPolicies() {
185 doReturn(true).when(this.peerPT).isTableSupported(PEER_ID);
186 doReturn(false).when(this.peerPT).isTableSupported(PEER_ID2);
187 doAnswer(invocation -> {
188 final Object[] args = invocation.getArguments();
189 if (PeerRole.Ibgp.equals(args[0])) {
191 } else if (PeerRole.Ebgp.equals(args[0])) {
196 }).when(this.peerPT).getPeerGroup(any(PeerRole.class));
198 doReturn(true).when(this.peerPT).isAddPathSupportedByPeer(PEER_ID);
199 doReturn(false).when(this.peerPT).isAddPathSupportedByPeer(PEER_ID2);
202 private void mockRibSupport() {
203 doReturn(ROUTE_ATTRIBUTES_IDENTIFIER).when(this.ribSupport).routeAttributesIdentifier();
204 doReturn(ROUTE_ID_PA_ADD_PATH).when(this.ribSupport).getRouteIdAddPath(any(Long.class), eq(ROUTE_ID_PA_ADD_PATH));
205 doReturn(null).when(this.ribSupport).getRouteIdAddPath(any(Long.class), eq(ROUTE_ID_PA));
206 doAnswer(invocation -> {
207 final Object[] args = invocation.getArguments();
208 final YangInstanceIdentifier yii = (YangInstanceIdentifier) args[0];
209 final PathArgument paa = (PathArgument) args[1];
211 if (ROUTE_ID_PA.equals(paa)) {
212 if (yii.equals(this.locRibTargetYii)) {
213 return this.routePaYii;
214 } else if (yii.equals(this.locRibOutTargetYii)) {
215 return this.routeRiboutYii;
216 } else if (yii.equals(this.locRibOutTargetYiiPeer2)) {
217 return this.routeRiboutYiiPeer2;
219 } else if (ROUTE_ID_PA_ADD_PATH.equals(paa)) {
220 if (yii.equals(this.locRibTargetYii)) {
221 return this.routePaAddPathYii;
222 } else if (yii.equals(this.locRibOutTargetYii)) {
223 return this.routeAddRiboutYii;
224 } else if (yii.equals(this.locRibOutTargetYiiPeer2)) {
225 return this.routeAddRiboutYiiPeer2;
229 }).when(this.ribSupport).routePath(any(YangInstanceIdentifier.class), any(PathArgument.class));
232 private NormalizedNode<?, ?> createAttr() {
233 final ContainerNode attributes = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(ATTRS_EXTENSION_Q))
234 .addChild(Builders.containerBuilder().withNodeIdentifier(ORIGIN_NID)
235 .addChild(Builders.leafBuilder().withNodeIdentifier(ORIGIN_VALUE_NID).withValue("igp").build()).build())
236 .addChild(Builders.containerBuilder().withNodeIdentifier(AS_PATH_NID)
237 .addChild(Builders.unkeyedListBuilder().withNodeIdentifier(SEGMENTS_NID).build()).build())
238 .addChild(Builders.containerBuilder().withNodeIdentifier(ATOMIC_NID).build()).build();
239 return ImmutableContainerNodeBuilder.create().withNodeIdentifier(ROUTE_ATTRIBUTES_IDENTIFIER)
240 .withChild(attributes).build();