2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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
8 package org.opendaylight.netvirt.vpnmanager.intervpnlink;
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.CheckedFuture;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
17 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
18 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkStateBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.inter.vpn.link.state.FirstEndpointState;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.inter.vpn.link.state.FirstEndpointStateBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.inter.vpn.link.state.SecondEndpointState;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.inter.vpn.link.state.SecondEndpointStateBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
28 import java.math.BigInteger;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.concurrent.Callable;
33 public class InterVpnLinkNodeAddTask implements Callable<List<ListenableFuture<Void>>> {
34 private static final String NBR_OF_DPNS_PROPERTY_NAME = "vpnservice.intervpnlink.number.dpns";
36 private DataBroker broker;
37 private BigInteger dpnId;
38 final IMdsalApiManager mdsalManager;
40 public InterVpnLinkNodeAddTask(final DataBroker broker, final IMdsalApiManager mdsalMgr, final BigInteger dpnId) {
43 this.mdsalManager = mdsalMgr;
47 public List<ListenableFuture<Void>> call() throws Exception {
48 List<ListenableFuture<Void>> result = new ArrayList<ListenableFuture<Void>>();
49 // check if there is any inter-vpn-link in with erroneous state
50 List<InterVpnLinkState> allInterVpnLinkState = InterVpnLinkUtil.getAllInterVpnLinkState(broker);
51 int numberOfDpns = Integer.getInteger(NBR_OF_DPNS_PROPERTY_NAME, 1);
53 List<BigInteger> firstDpnList = new ArrayList<BigInteger>();
54 List<BigInteger> secondDpnList = new ArrayList<BigInteger>();
55 for (InterVpnLinkState interVpnLinkState : allInterVpnLinkState) {
56 // if the inter-vpn-link is erroneous and any of its endPoints has no dpns associated
57 if (shouldConfigureLinkIntoDpn(interVpnLinkState, this.dpnId, numberOfDpns)) {
58 firstDpnList.add(dpnId);
59 secondDpnList = firstDpnList;
60 // TODO: Limitation to be solved later
61 // List<BigInteger> secondDpnList = VpnUtil.pickRandomDPNs(broker, numberOfDpns, firstDpnList);
62 secondDpnList = firstDpnList;
63 installLPortDispatcherTable(interVpnLinkState, firstDpnList, secondDpnList);
64 CheckedFuture<Void, TransactionCommitFailedException> futures =
65 updateInterVpnLinkState(interVpnLinkState, firstDpnList, secondDpnList, numberOfDpns);
72 private boolean shouldConfigureLinkIntoDpn(InterVpnLinkState interVpnLinkState, BigInteger dpnId, int numberOfDpns) {
74 if (interVpnLinkState.getState().equals(InterVpnLinkState.State.Error)) {
75 if ((interVpnLinkState.getFirstEndpointState().getDpId() == null
76 || interVpnLinkState.getFirstEndpointState().getDpId().isEmpty())
77 || (interVpnLinkState.getSecondEndpointState().getDpId() == null
78 || interVpnLinkState.getSecondEndpointState().getDpId().isEmpty())) {
80 } else if (!interVpnLinkState.getFirstEndpointState().getDpId().contains(dpnId)
81 && !interVpnLinkState.getSecondEndpointState().getDpId().contains(dpnId)
82 && (interVpnLinkState.getFirstEndpointState().getDpId().size() < numberOfDpns)) {
90 private CheckedFuture<Void, TransactionCommitFailedException>
91 updateInterVpnLinkState(InterVpnLinkState interVpnLinkState, List<BigInteger> firstDpnList,
92 List<BigInteger> secondDpnList, int numberOfDpns) {
93 FirstEndpointState firstEndPointState =
94 new FirstEndpointStateBuilder(interVpnLinkState.getFirstEndpointState())
95 .setDpId(firstDpnList).build();
96 SecondEndpointState secondEndPointState =
97 new SecondEndpointStateBuilder(interVpnLinkState.getSecondEndpointState())
98 .setDpId(secondDpnList).build();
99 InterVpnLinkState newInterVpnLinkState = new InterVpnLinkStateBuilder(interVpnLinkState)
100 .setState(InterVpnLinkState.State.Active)
101 .setFirstEndpointState(firstEndPointState)
102 .setSecondEndpointState(secondEndPointState)
104 WriteTransaction tx = broker.newWriteOnlyTransaction();
105 tx.merge(LogicalDatastoreType.CONFIGURATION,
106 InterVpnLinkUtil.getInterVpnLinkStateIid(interVpnLinkState.getInterVpnLinkName()), newInterVpnLinkState, true);
107 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
111 private void installLPortDispatcherTable(InterVpnLinkState interVpnLinkState, List<BigInteger> firstDpnList,
112 List<BigInteger> secondDpnList) {
113 Optional<InterVpnLink> vpnLink = InterVpnLinkUtil.getInterVpnLinkByName(broker, interVpnLinkState.getKey().getInterVpnLinkName());
114 if (vpnLink.isPresent()) {
115 Uuid firstEndpointVpnUuid = vpnLink.get().getFirstEndpoint().getVpnUuid();
116 Uuid secondEndpointVpnUuid = vpnLink.get().getSecondEndpoint().getVpnUuid();
117 // Note that in the DPN of the firstEndpoint we install the lportTag of the secondEndpoint and viceversa
118 InterVpnLinkUtil.installLPortDispatcherTableFlow(broker, mdsalManager, vpnLink.get(), firstDpnList,
119 secondEndpointVpnUuid,
120 interVpnLinkState.getSecondEndpointState().getLportTag());
121 InterVpnLinkUtil.installLPortDispatcherTableFlow(broker, mdsalManager, vpnLink.get(), secondDpnList,
122 firstEndpointVpnUuid,
123 interVpnLinkState.getFirstEndpointState().getLportTag());
124 // Update the VPN -> DPNs Map.
125 // Note: when a set of DPNs is calculated for Vpn1, these DPNs are added to the VpnToDpn map of Vpn2. Why?
126 // because we do the handover from Vpn1 to Vpn2 in those DPNs, so in those DPNs we must know how to reach
127 // to Vpn2 targets. If new Vpn2 targets are added later, the Fib will be maintained in these DPNs even if
128 // Vpn2 is not physically present there.
129 InterVpnLinkUtil.updateVpnToDpnMap(broker, firstDpnList, secondEndpointVpnUuid);
130 InterVpnLinkUtil.updateVpnToDpnMap(broker, secondDpnList, firstEndpointVpnUuid);