a41480542d8218ab23457180bc2de448a61ebfd7
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / intervpnlink / InterVpnLinkListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.vpnmanager.intervpnlink;
9
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
17 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
22 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.NwConstants;
25 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
26 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
27 import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
28 import org.opendaylight.netvirt.vpnmanager.VpnConstants;
29 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.*;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinkCreationError;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinkCreationErrorBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.creation.error.InterVpnLinkCreationErrorMessage;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.creation.error.InterVpnLinkCreationErrorMessageBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkStateBuilder;
44 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;
45 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;
46 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;
47 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;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLinkKey;
50 import org.opendaylight.yangtools.concepts.ListenerRegistration;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.opendaylight.yangtools.yang.common.RpcResult;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 import java.math.BigInteger;
57 import java.util.ArrayList;
58 import java.util.List;
59 import java.util.concurrent.ExecutionException;
60 import java.util.concurrent.Future;
61
62 public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLink> {
63     private static final Logger logger = LoggerFactory.getLogger(InterVpnLinkListener.class);
64     private static final String NBR_OF_DPNS_PROPERTY_NAME = "vpnservice.intervpnlink.number.dpns";
65     private static final int INVALID_ID = 0;
66
67     private IMdsalApiManager mdsalManager;
68     private IdManagerService idManager;
69     private IBgpManager bgpManager;
70     private NotificationPublishService notificationsService;
71
72     private ListenerRegistration<DataChangeListener> listenerRegistration;
73     private final DataBroker broker;
74
75
76     public InterVpnLinkListener(DataBroker db, IdManagerService idManager, IMdsalApiManager mdsalManager,
77                                 IBgpManager bgpManager, NotificationPublishService notifService) {
78         super(InterVpnLink.class);
79         this.broker = db;
80         this.idManager = idManager;
81         this.mdsalManager = mdsalManager;
82         this.bgpManager = bgpManager;
83         this.notificationsService = notifService;
84         this.registerListener(db);
85     }
86
87     public void close() {
88         if (listenerRegistration != null) {
89             try {
90                 listenerRegistration.close();
91             } catch (final Exception e) {
92                 logger.error("Error when cleaning up DataChangeListener.", e);
93             }
94             listenerRegistration = null;
95         }
96     }
97
98
99     /**
100      * Register the databroker to all the possible changes from MDSAL - InterVpnLink class
101      *
102      * @param db dataBroker service reference
103      */
104     private void registerListener(DataBroker db) {
105         try {
106             this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
107                                                                       this.getWildCardPath(),
108                                                                       this,
109                                                                       AsyncDataBroker.DataChangeScope.SUBTREE);
110         } catch (Exception e) {
111             logger.error("InterVpnLinkListener: DataChange listener registration fail!", e);
112             throw new IllegalStateException("InterVpnLinkListener: registration Listener failed.", e);
113         }
114     }
115
116     private InstanceIdentifier<InterVpnLink> getWildCardPath() {
117         return InstanceIdentifier.create(InterVpnLinks.class).child(InterVpnLink.class);
118     }
119
120     private String getInterVpnLinkIfaceName(String vpnUuid, BigInteger dpnId ) {
121         return String.format("InterVpnLink.%s.%s", vpnUuid, dpnId.toString());
122     }
123
124     @Override
125     protected void add(InstanceIdentifier<InterVpnLink> identifier, InterVpnLink add) {
126
127         int numberOfDpns = Integer.getInteger(NBR_OF_DPNS_PROPERTY_NAME, 1);
128         // Create VpnLink state
129         InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(add.getName());
130         InterVpnLinkState vpnLinkState = new InterVpnLinkStateBuilder().setInterVpnLinkName(add.getName()).build();
131         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid, vpnLinkState);
132
133         InterVpnLinkKey key = add.getKey();
134         Uuid firstEndpointVpnUuid = add.getFirstEndpoint().getVpnUuid();
135         Uuid secondEndpointVpnUuid = add.getSecondEndpoint().getVpnUuid();
136         // First VPN
137         if (!checkVpnAvailability(key, firstEndpointVpnUuid)) {
138             String errMsg = String.format("Vpn already associated with a previous inter-vpn-link {}",
139                                           firstEndpointVpnUuid);
140             logger.error(errMsg);
141             setInError(vpnLinkStateIid, vpnLinkState, errMsg);
142             return;
143         }
144
145         // Second VPN
146         if (!checkVpnAvailability(key, secondEndpointVpnUuid)) {
147             String errMsg = String.format("Vpn already associated with a previous inter-vpn-link {}",
148                                           secondEndpointVpnUuid);
149             logger.error(errMsg);
150             setInError(vpnLinkStateIid, vpnLinkState, errMsg);
151             return;
152         }
153
154         // TODO: Doing like this we are retrieving operative DPNs from MDSAL when we just need one. Fix it
155         List<BigInteger> firstDpnList = VpnUtil.pickRandomDPNs(broker, numberOfDpns, null);
156         if (firstDpnList != null && !firstDpnList.isEmpty()) {
157             // TODO: Limitation to be solved later
158             // List<BigInteger> secondDpnList = VpnUtil.pickRandomDPNs(broker, numberOfDpns, firstDpnList);
159             List<BigInteger> secondDpnList = firstDpnList;
160
161             Integer firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
162             Integer secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
163             FirstEndpointState firstEndPointState =
164                 new FirstEndpointStateBuilder().setVpnUuid(firstEndpointVpnUuid).setDpId(firstDpnList)
165                                                .setLportTag(firstVpnLportTag).build();
166             SecondEndpointState secondEndPointState =
167                 new SecondEndpointStateBuilder().setVpnUuid(secondEndpointVpnUuid).setDpId(secondDpnList)
168                                                 .setLportTag(secondVpnLportTag).build();
169
170             InterVpnLinkUtil.updateInterVpnLinkState(broker, add.getName(), InterVpnLinkState.State.Active, firstEndPointState,
171                                             secondEndPointState);
172
173             // Note that in the DPN of the firstEndpoint we install the lportTag of the secondEndpoint and viceversa
174             InterVpnLinkUtil.installLPortDispatcherTableFlow(broker, mdsalManager, add, firstDpnList,
175                                                     secondEndpointVpnUuid, secondVpnLportTag);
176             InterVpnLinkUtil.installLPortDispatcherTableFlow(broker, mdsalManager, add, secondDpnList,
177                                                     firstEndpointVpnUuid, firstVpnLportTag);
178             // Update the VPN -> DPNs Map.
179             // Note: when a set of DPNs is calculated for Vpn1, these DPNs are added to the VpnToDpn map of Vpn2. Why?
180             // because we do the handover from Vpn1 to Vpn2 in those DPNs, so in those DPNs we must know how to reach
181             // to Vpn2 targets. If new Vpn2 targets are added later, the Fib will be maintained in these DPNs even if
182             // Vpn2 is not physically present there.
183             InterVpnLinkUtil.updateVpnToDpnMap(broker, firstDpnList, secondEndpointVpnUuid);
184             InterVpnLinkUtil.updateVpnToDpnMap(broker, secondDpnList, firstEndpointVpnUuid);
185
186             // Now, if the corresponding flags are activated, there will be some routes exchange
187             leakRoutesIfNeeded(add);
188         } else {
189             // If there is no connection to DPNs, the InterVpnLink is created and the InterVpnLinkState is also created
190             // with the corresponding LPortTags but no DPN is assigned since there is no DPN operative.
191             Integer firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + firstEndpointVpnUuid.getValue());
192             Integer secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + secondEndpointVpnUuid.getValue());
193             FirstEndpointState firstEndPointState =
194                 new FirstEndpointStateBuilder().setVpnUuid(firstEndpointVpnUuid)
195                                                .setLportTag(firstVpnLportTag).build();
196             SecondEndpointState secondEndPointState =
197                 new SecondEndpointStateBuilder().setVpnUuid(secondEndpointVpnUuid)
198                                                 .setLportTag(secondVpnLportTag).build();
199             InterVpnLinkUtil.updateInterVpnLinkState(broker, add.getName(), InterVpnLinkState.State.Error, firstEndPointState,
200                                             secondEndPointState);
201         }
202
203
204     }
205
206     private void leakRoutesIfNeeded(InterVpnLink vpnLink) {
207
208         // The type of routes to exchange depend on the leaking flags that have been activated
209         List<RouteOrigin> originsToConsider = new ArrayList<>();
210         if ( vpnLink.isBgpRoutesLeaking() ) {
211             originsToConsider.add(RouteOrigin.BGP);
212         }
213
214         /* For now, only BGP leaking. Leave this here for when the other leakings are activated
215         if ( vpnLink.isConnectedRoutesLeaking() ) {
216             originsToConsider.add(RouteOrigin.CONNECTED);
217         }
218         if ( vpnLink.isStaticRoutesLeaking() ) {
219             originsToConsider.add(RouteOrigin.STATIC);
220             NOTE: There are 2 types of static routes depending on the nexthop:
221               + static route when nexthop is a VM, the Dc-GW or a DPNIP
222               + static route when nexthop is an InterVPN Link
223             Only the 1st type should be considered since the 2nd has a special treatment
224         } */
225         String vpn1Uuid = vpnLink.getFirstEndpoint().getVpnUuid().getValue();
226         String vpn2Uuid = vpnLink.getSecondEndpoint().getVpnUuid().getValue();
227
228         if ( ! originsToConsider.isEmpty() ) {
229             // 1st Endpoint ==> 2nd endpoint
230             leakRoutes(vpnLink, vpn1Uuid, vpn2Uuid, originsToConsider);
231
232             // 2nd Endpoint ==> 1st endpoint
233             leakRoutes(vpnLink, vpnLink.getSecondEndpoint().getVpnUuid().getValue(),
234                        vpnLink.getFirstEndpoint().getVpnUuid().getValue(),
235                        originsToConsider);
236         }
237
238         // Static routes in Vpn1 pointing to Vpn2's endpoint
239         leakExtraRoutesToVpnEndpoint(vpnLink, vpn1Uuid, vpn2Uuid);
240
241         // Static routes in Vpn2 pointing to Vpn1's endpoint
242         leakExtraRoutesToVpnEndpoint(vpnLink, vpn2Uuid, vpn1Uuid);
243     }
244
245     private void leakRoutes(InterVpnLink vpnLink, String srcVpnUuid, String dstVpnUuid,
246                             List<RouteOrigin> originsToConsider) {
247         String srcVpnRd = VpnUtil.getVpnRd(broker, srcVpnUuid);
248         String dstVpnRd = VpnUtil.getVpnRd(broker, dstVpnUuid);
249         List<VrfEntry> srcVpnRemoteVrfEntries = VpnUtil.getVrfEntriesByOrigin(broker, srcVpnRd, originsToConsider);
250         for ( VrfEntry vrfEntry : srcVpnRemoteVrfEntries ) {
251             long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
252                                              VpnUtil.getNextHopLabelKey(dstVpnRd, vrfEntry.getDestPrefix()));
253
254             VpnUtil.leakRoute(broker, bgpManager, vpnLink, srcVpnUuid, dstVpnUuid,
255                               vrfEntry.getDestPrefix(), label);
256         }
257     }
258
259     /*
260      * Checks if there are static routes in Vpn1 whose nexthop is Vpn2's endpoint. Those routes must be leaked to Vpn1.
261      *
262      * @param vpnLink
263      * @param vpn1Uuid
264      * @param vpn2Uuid
265      */
266     private void leakExtraRoutesToVpnEndpoint(InterVpnLink vpnLink, String vpn1Uuid, String vpn2Uuid) {
267
268         String vpn1Rd = VpnUtil.getVpnRd(broker, vpn1Uuid);
269         String vpn2Endpoint = vpnLink.getSecondEndpoint().getIpAddress().getValue();
270         List<VrfEntry> allVpnVrfEntries = VpnUtil.getAllVrfEntries(broker, vpn1Rd);
271         for ( VrfEntry vrfEntry : allVpnVrfEntries ) {
272             if ( vrfEntry.getNextHopAddressList() != null
273                 && vrfEntry.getNextHopAddressList().contains(vpn2Endpoint) ) {
274                 // Vpn1 has a route pointing to Vpn2's endpoint. Forcing the leaking of the route will update the
275                 // BGP accordingly
276                 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
277                                                   VpnUtil.getNextHopLabelKey(vpn1Rd, vrfEntry.getDestPrefix()));
278
279                 VpnUtil.leakRoute(broker, bgpManager, vpnLink, vpn2Uuid, vpn1Uuid, vrfEntry.getDestPrefix(),
280                                   label, RouteOrigin.value(vrfEntry.getOrigin()));
281             }
282         }
283
284     }
285
286     private boolean checkVpnAvailability(InterVpnLinkKey key, Uuid vpnId) {
287         Preconditions.checkNotNull(vpnId);
288
289         List<InterVpnLink> interVpnLinks = VpnUtil.getAllInterVpnLinks(broker);
290         if ( interVpnLinks != null ) {
291             for (InterVpnLink interVpnLink : interVpnLinks) {
292                 if (!key.equals(interVpnLink.getKey())
293                     && (vpnId.equals(interVpnLink.getFirstEndpoint().getVpnUuid())
294                         || vpnId.equals(interVpnLink.getSecondEndpoint().getVpnUuid()))) {
295                     return false;
296                 }
297             }
298         }
299         return true;
300     }
301
302
303     @Override
304     protected void remove(InstanceIdentifier<InterVpnLink> identifier, InterVpnLink del) {
305
306         // Remove learnt routes
307         // Remove entries in the LPortDispatcher table
308         // Remove the corresponding entries in InterVpnLinkState
309
310         // For each endpoint, remove all routes that have been learnt by intervpnLink
311         String vpn1Uuid = del.getFirstEndpoint().getVpnUuid().getValue();
312         String rd1 = VpnUtil.getVpnRdFromVpnInstanceConfig(broker, vpn1Uuid);
313         VpnUtil.removeVrfEntriesByOrigin(broker, rd1, RouteOrigin.INTERVPN);
314         VpnUtil.removeVrfEntriesByNexthop(broker, rd1, del.getSecondEndpoint().getIpAddress().getValue());
315
316         String vpn2Uuid = del.getSecondEndpoint().getVpnUuid().getValue();
317         String rd2 = VpnUtil.getVpnRdFromVpnInstanceConfig(broker, vpn2Uuid);
318         VpnUtil.removeVrfEntriesByOrigin(broker, rd2, RouteOrigin.INTERVPN);
319         VpnUtil.removeVrfEntriesByNexthop(broker, rd2, del.getFirstEndpoint().getIpAddress().getValue());
320
321         InterVpnLinkState interVpnLinkState = VpnUtil.getInterVpnLinkState(broker, del.getName());
322         Integer firstEndpointLportTag = interVpnLinkState.getFirstEndpointState().getLportTag();
323
324         Integer secondEndpointLportTag = interVpnLinkState.getSecondEndpointState().getLportTag();
325
326         // Remmoving the flow entries in LPortDispatcher table in 1st Endpoint DPNs
327         for ( BigInteger dpnId : interVpnLinkState.getFirstEndpointState().getDpId() ) {
328             String flowRef = InterVpnLinkUtil.getLportDispatcherFlowRef(del.getName(), secondEndpointLportTag);
329             FlowKey flowKey = new FlowKey(new FlowId(flowRef));
330             Flow flow = new FlowBuilder().setKey(flowKey).setId(new FlowId(flowRef))
331                                          .setTableId(NwConstants.LPORT_DISPATCHER_TABLE).setFlowName(flowRef)
332                                          .build();
333             mdsalManager.removeFlow(dpnId, flow);
334
335             // Also remove the 'fake' iface from the VpnToDpn map
336             VpnUtil.removeIfaceFromVpnToDpnMap(broker, rd1, dpnId, getInterVpnLinkIfaceName(vpn1Uuid, dpnId));
337         }
338
339         // Removing the flow entries in 2nd Endpoint DPNs
340         for ( BigInteger dpnId : interVpnLinkState.getSecondEndpointState().getDpId() ) {
341             String flowRef = InterVpnLinkUtil.getLportDispatcherFlowRef(del.getName(), firstEndpointLportTag);
342             FlowKey flowKey = new FlowKey(new FlowId(flowRef));
343             Flow flow = new FlowBuilder().setKey(flowKey).setId(new FlowId(flowRef))
344                                          .setTableId(NwConstants.LPORT_DISPATCHER_TABLE).setFlowName(flowRef)
345                                          .build();
346             mdsalManager.removeFlow(dpnId, flow);
347
348             // Also remove the 'fake' iface from the VpnToDpn map
349             VpnUtil.removeIfaceFromVpnToDpnMap(broker, rd2, dpnId, getInterVpnLinkIfaceName(vpn2Uuid, dpnId));
350         }
351
352         // Release idManager wit LPortTag associated to endpoints
353         InterVpnLinkKey key = del.getKey();
354         Uuid firstEndpointVpnUuid = del.getFirstEndpoint().getVpnUuid();
355         Uuid secondEndpointVpnUuid = del.getSecondEndpoint().getVpnUuid();
356         releaseVpnLinkLPortTag(key.getName() + firstEndpointVpnUuid.getValue());
357         releaseVpnLinkLPortTag(key.getName() + secondEndpointVpnUuid.getValue());
358
359         // Routes with nextHop pointing to an end-point of the inter-vpn-link are populated into FIB table.
360         // The action in that case is a nx_resubmit to LPortDispatcher table. This is done in FibManager.
361         // At this point. we need to check if is there any entry in FIB table pointing to LPortDispatcher table.
362         // Remove it in that case.
363
364         // 1stEndPoint dpns
365         for ( BigInteger dpnId : interVpnLinkState.getFirstEndpointState().getDpId() ) {
366             removeRouteFromInterVpnLink(dpnId, del.getName(), del.getSecondEndpoint().getIpAddress().getValue());
367         }
368
369         // 2ndtEndPoint dpns
370         for ( BigInteger dpnId : interVpnLinkState.getSecondEndpointState().getDpId() ) {
371             removeRouteFromInterVpnLink(dpnId, del.getName(), del.getFirstEndpoint().getIpAddress().getValue());
372         }
373
374         // Removing the InterVpnLinkState
375         InstanceIdentifier<InterVpnLinkState> interVpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(del.getName());
376         VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, interVpnLinkStateIid);
377     }
378
379     private void releaseVpnLinkLPortTag(String idKey) {
380         ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setPoolName(IfmConstants.IFM_IDPOOL_NAME)
381                                                                    .setIdKey(idKey).build();
382         idManager.releaseId(releaseIdInput);
383     }
384
385     @Override
386     protected void update(InstanceIdentifier<InterVpnLink> identifier, InterVpnLink original, InterVpnLink update) {
387      // TODO
388     }
389
390     private String getInterVpnFibFlowRef(BigInteger dpnId, short tableId, String interVpnLinkName, String nextHop ) {
391         return new StringBuilder(64).append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
392             .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
393             .append(interVpnLinkName).append(NwConstants.FLOWID_SEPARATOR)
394             .append(nextHop).toString();
395     }
396
397     private void removeRouteFromInterVpnLink(BigInteger dpnId, String interVpnLinkName, final String nextHop) {
398         String flowRef = getInterVpnFibFlowRef(dpnId, NwConstants.L3_FIB_TABLE, interVpnLinkName, nextHop);
399         FlowKey flowKey = new FlowKey(new FlowId(flowRef));
400         Flow flow = new FlowBuilder().setKey(flowKey).setId(new FlowId(flowRef))
401                 .setTableId(NwConstants.L3_FIB_TABLE).setFlowName(flowRef)
402                 .build();
403         mdsalManager.removeFlow(dpnId, flow);
404     }
405
406
407     private Integer allocateVpnLinkLportTag(String idKey) {
408         AllocateIdInput getIdInput =
409                 new AllocateIdInputBuilder().setPoolName(IfmConstants.IFM_IDPOOL_NAME).setIdKey(idKey).build();
410         try {
411             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
412             RpcResult<AllocateIdOutput> rpcResult = result.get();
413             if(rpcResult.isSuccessful()) {
414                 return rpcResult.getResult().getIdValue().intValue();
415             } else {
416                 logger.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
417             }
418         } catch (InterruptedException | ExecutionException e) {
419             logger.warn("Exception when getting Unique Id",e);
420         }
421         return INVALID_ID;
422     }
423
424     protected void setInError(final InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid,
425                               final InterVpnLinkState vpnLinkState,
426                               String errorMsg) {
427         // Setting InterVPNLink in error state in MDSAL
428         InterVpnLinkState vpnLinkErrorState =
429            new InterVpnLinkStateBuilder(vpnLinkState).setState(InterVpnLinkState.State.Error)
430                                                      .setErrorDescription(errorMsg)
431                                                      .build();
432         WriteTransaction tx = broker.newWriteOnlyTransaction();
433         tx.put(LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid, vpnLinkErrorState, true);
434         tx.submit();
435
436         // Sending out an error Notification
437         InterVpnLinkCreationErrorMessage errMsg =
438             new InterVpnLinkCreationErrorMessageBuilder().setErrorMessage(errorMsg).build();
439         InterVpnLinkCreationError notif =
440             new InterVpnLinkCreationErrorBuilder().setInterVpnLinkCreationErrorMessage(errMsg).build();
441         final ListenableFuture<? extends Object> eventFuture = this.notificationsService.offerNotification(notif);
442         Futures.addCallback(eventFuture, new FutureCallback<Object>() {
443             @Override
444             public void onFailure(Throwable error) {
445                 logger.warn("Error when sending notification about InterVpnLink creation issue. InterVpnLink name={}. Error={}",
446                             vpnLinkState.getInterVpnLinkName(), vpnLinkState, error);
447             }
448
449             @Override
450             public void onSuccess(Object arg) {
451                 logger.trace("Error notification for InterVpnLink successfully sent. VpnLink={} error={}",
452                              vpnLinkState.getInterVpnLinkName(), vpnLinkState);
453             }
454         });
455     }
456 }