2 * Copyright (c) 2015 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.vpnservice;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.List;
15 import org.opendaylight.bgpmanager.api.IBgpManager;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
20 import org.opendaylight.yangtools.concepts.ListenerRegistration;
21 import org.opendaylight.yangtools.yang.binding.DataObject;
22 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
23 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1Builder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import com.google.common.base.Optional;
39 import com.google.common.util.concurrent.FutureCallback;
40 import com.google.common.util.concurrent.Futures;
42 public class VpnManager extends AbstractDataChangeListener<VpnInstance> implements AutoCloseable {
43 private static final Logger LOG = LoggerFactory.getLogger(VpnManager.class);
44 private ListenerRegistration<DataChangeListener> listenerRegistration, fibListenerRegistration;
45 private final DataBroker broker;
46 private final IBgpManager bgpManager;
47 private final FibEntriesListener fibListener;
49 private static final FutureCallback<Void> DEFAULT_CALLBACK =
50 new FutureCallback<Void>() {
51 public void onSuccess(Void result) {
52 LOG.debug("Success in Datastore operation");
55 public void onFailure(Throwable error) {
56 LOG.error("Error in Datastore operation", error);
61 * Listens for data change related to VPN Instance
62 * Informs the BGP about VRF information
64 * @param db - dataBroker reference
66 public VpnManager(final DataBroker db, final IBgpManager bgpManager) {
67 super(VpnInstance.class);
69 this.bgpManager = bgpManager;
70 this.fibListener = new FibEntriesListener();
74 private void registerListener(final DataBroker db) {
76 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
77 getWildCardPath(), VpnManager.this, DataChangeScope.SUBTREE);
78 fibListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
79 getFibEntryListenerPath(), fibListener, DataChangeScope.BASE);
80 } catch (final Exception e) {
81 LOG.error("VPN Service DataChange listener registration fail!", e);
82 throw new IllegalStateException("VPN Service registration Listener failed.", e);
87 protected void remove(InstanceIdentifier<VpnInstance> identifier,
89 // TODO Auto-generated method stub
93 protected void update(InstanceIdentifier<VpnInstance> identifier,
94 VpnInstance original, VpnInstance update) {
95 // TODO Auto-generated method stub
99 protected void add(InstanceIdentifier<VpnInstance> identifier,
101 LOG.info("key: {}, value: {}" +identifier, value);
102 //TODO: Generate VPN ID for this instance, where to store in model ... ?
104 InstanceIdentifier<VpnInstance1> augId = identifier.augmentation(VpnInstance1.class);
105 Optional<VpnInstance1> vpnAugmenation = read(LogicalDatastoreType.CONFIGURATION, augId);
106 if(vpnAugmenation.isPresent()) {
107 VpnInstance1 vpn = vpnAugmenation.get();
108 vpnId = vpn.getVpnId();
109 LOG.info("VPN ID is {}", vpnId);
112 VpnInstance opValue = new VpnInstanceBuilder(value).
113 addAugmentation(VpnInstance1.class, new VpnInstance1Builder().setVpnId(vpnId).build()).build();
115 asyncWrite(LogicalDatastoreType.OPERATIONAL, identifier, opValue, DEFAULT_CALLBACK);
117 //TODO: Add VRF to BGP
118 //public void addVrf(String rd, Collection<String> importRts, Collection<String> exportRts)
119 VpnAfConfig config = value.getIpv4Family();
120 String rd = config.getRouteDistinguisher();
121 List<String> importRts = Arrays.asList(config.getImportRoutePolicy().split(","));
122 List<String> exportRts = Arrays.asList(config.getExportRoutePolicy().split(","));
124 bgpManager.addVrf(rd, importRts, exportRts);
125 } catch(Exception e) {
126 LOG.error("Exception when adding VRF to BGP", e);
130 private InstanceIdentifier<?> getWildCardPath() {
131 return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
134 private InstanceIdentifier<?> getFibEntryListenerPath() {
135 return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class)
136 .child(VrfEntry.class);
140 public void close() throws Exception {
141 if (listenerRegistration != null) {
143 listenerRegistration.close();
144 } catch (final Exception e) {
145 LOG.error("Error when cleaning up Vpn DataChangeListener.", e);
147 listenerRegistration = null;
149 if (fibListenerRegistration != null) {
151 fibListenerRegistration.close();
152 } catch (final Exception e) {
153 LOG.error("Error when cleaning up Fib entries DataChangeListener.", e);
155 fibListenerRegistration = null;
157 LOG.trace("VPN Manager Closed");
160 private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
161 InstanceIdentifier<T> path) {
163 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
165 Optional<T> result = Optional.absent();
167 result = tx.read(datastoreType, path).get();
168 } catch (Exception e) {
169 throw new RuntimeException(e);
175 private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
176 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
177 WriteTransaction tx = broker.newWriteOnlyTransaction();
178 tx.put(datastoreType, path, data, true);
179 Futures.addCallback(tx.submit(), callback);
182 private VpnInstance getVpnForRD(String rd) {
183 InstanceIdentifier<VpnInstances> id = InstanceIdentifier.create(VpnInstances.class);
184 Optional<VpnInstances> vpnInstances = read(LogicalDatastoreType.OPERATIONAL, id);
185 if(vpnInstances.isPresent()) {
186 List<VpnInstance> vpns = vpnInstances.get().getVpnInstance();
187 for(VpnInstance vpn : vpns) {
188 if(vpn.getIpv4Family().getRouteDistinguisher().equals(rd)) {
196 private class FibEntriesListener extends AbstractDataChangeListener<VrfEntry> {
198 public FibEntriesListener() {
199 super(VrfEntry.class);
203 protected void remove(InstanceIdentifier<VrfEntry> identifier,
205 // TODO Auto-generated method stub
210 protected void update(InstanceIdentifier<VrfEntry> identifier,
211 VrfEntry original, VrfEntry update) {
212 // TODO Auto-generated method stub
217 protected void add(InstanceIdentifier<VrfEntry> identifier,
219 LOG.info("Key : " + identifier + " value : " + add);
220 final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
221 String rd = key.getRouteDistinguisher();
222 Long label = add.getLabel();
223 VpnInstance vpn = getVpnForRD(rd);
225 InstanceIdentifier<VpnInstance> id = VpnUtil.getVpnInstanceIdentifier(vpn.getVpnInstanceName());
226 InstanceIdentifier<VpnInstance1> augId = id.augmentation(VpnInstance1.class);
227 Optional<VpnInstance1> vpnAugmenation = read(LogicalDatastoreType.OPERATIONAL, augId);
228 if(vpnAugmenation.isPresent()) {
229 VpnInstance1 vpnAug = vpnAugmenation.get();
230 List<Long> routeIds = vpnAug.getRouteEntryId();
231 if(routeIds == null) {
232 routeIds = new ArrayList<>();
234 LOG.info("Adding label to vpn info " + label);
236 asyncWrite(LogicalDatastoreType.OPERATIONAL, augId,
237 new VpnInstance1Builder(vpnAug).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
239 LOG.info("VPN Augmentation not found");
242 LOG.warn("No VPN Instance found for RD: {}", rd);