2 * Copyright © 2015, 2017 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.fibmanager;
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.CheckedFuture;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.Future;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
21 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.genius.itm.globals.ITMConstants;
25 import org.opendaylight.genius.mdsalutil.ActionInfo;
26 import org.opendaylight.genius.mdsalutil.BucketInfo;
27 import org.opendaylight.genius.mdsalutil.GroupEntity;
28 import org.opendaylight.genius.mdsalutil.MDSALUtil;
29 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
30 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
31 import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
32 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
33 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
34 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldVlanVid;
35 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
36 import org.opendaylight.netvirt.elanmanager.api.IElanService;
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
38 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
39 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetInternalOrExternalInterfaceNameOutput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeBase;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeFlat;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVlan;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.L3nexthop;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthops;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.ConfTransportTypeL3vpn;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.ConfTransportTypeL3vpnBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCase;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCase;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
90 import org.opendaylight.yangtools.yang.binding.DataObject;
91 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
92 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
93 import org.opendaylight.yangtools.yang.common.RpcResult;
94 import org.slf4j.Logger;
95 import org.slf4j.LoggerFactory;
97 public class NexthopManager implements AutoCloseable {
98 private static final Logger LOG = LoggerFactory.getLogger(NexthopManager.class);
99 private final DataBroker dataBroker;
100 private final IMdsalApiManager mdsalApiManager;
101 private final OdlInterfaceRpcService interfaceManager;
102 private final ItmRpcService itmManager;
103 private final IdManagerService idManager;
104 private final IElanService elanService;
105 private static final short LPORT_INGRESS_TABLE = 0;
106 private static final short LFIB_TABLE = 20;
107 private static final short FIB_TABLE = 21;
108 private static final short DEFAULT_FLOW_PRIORITY = 10;
109 private static final String NEXTHOP_ID_POOL_NAME = "nextHopPointerPool";
110 private static final long FIXED_DELAY_IN_MILLISECONDS = 4000;
111 private L3VPNTransportTypes configuredTransportTypeL3VPN = L3VPNTransportTypes.Invalid;
112 private Long waitTimeForSyncInstall;
114 private static final FutureCallback<Void> DEFAULT_CALLBACK =
115 new FutureCallback<Void>() {
117 public void onSuccess(Void result) {
118 LOG.debug("Success in Datastore write operation");
122 public void onFailure(Throwable error) {
123 LOG.error("Error in Datastore write operation", error);
130 * Provides nexthop functions.
131 * Creates group ID pool
133 * @param dataBroker - dataBroker reference
134 * @param mdsalApiManager - mdsalApiManager reference
135 * @param idManager - idManager reference
136 * @param interfaceManager - interfaceManager reference
137 * @param itmManager - itmManager reference
139 public NexthopManager(final DataBroker dataBroker,
140 final IMdsalApiManager mdsalApiManager,
141 final IdManagerService idManager,
142 final OdlInterfaceRpcService interfaceManager,
143 final ItmRpcService itmManager,
144 final IElanService elanService) {
145 this.dataBroker = dataBroker;
146 this.mdsalApiManager = mdsalApiManager;
147 this.idManager = idManager;
148 this.interfaceManager = interfaceManager;
149 this.itmManager = itmManager;
150 this.elanService = elanService;
151 waitTimeForSyncInstall = Long.getLong("wait.time.sync.install");
152 if (waitTimeForSyncInstall == null) {
153 waitTimeForSyncInstall = 1000L;
159 private void createIdPool() {
160 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
161 .setPoolName(NEXTHOP_ID_POOL_NAME)
166 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
167 if ((result != null) && (result.get().isSuccessful())) {
168 LOG.info("Created IdPool for NextHopPointerPool");
170 } catch (InterruptedException | ExecutionException e) {
171 LOG.error("Failed to create idPool for NextHopPointerPool", e);
175 private BigInteger getDpnId(String ofPortId) {
176 String[] fields = ofPortId.split(":");
177 BigInteger dpn = new BigInteger(fields[1]);
178 LOG.debug("DpnId: {}", dpn);
182 private String getNextHopKey(long vpnId, String ipAddress) {
183 return "nexthop." + vpnId + ipAddress;
186 private String getNextHopKey(String ifName, String ipAddress) {
187 return "nexthop." + ifName + ipAddress;
190 protected long createNextHopPointer(String nexthopKey) {
191 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
192 .setPoolName(NEXTHOP_ID_POOL_NAME).setIdKey(nexthopKey)
194 //TODO: Proper error handling once IdManager code is complete
196 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
197 RpcResult<AllocateIdOutput> rpcResult = result.get();
198 return rpcResult.getResult().getIdValue();
199 } catch (NullPointerException | InterruptedException | ExecutionException e) {
205 protected void removeNextHopPointer(String nexthopKey) {
206 ReleaseIdInput idInput = new ReleaseIdInputBuilder()
207 .setPoolName(NEXTHOP_ID_POOL_NAME)
208 .setIdKey(nexthopKey).build();
210 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
211 RpcResult<Void> rpcResult = result.get();
212 if (!rpcResult.isSuccessful()) {
213 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
215 } catch (InterruptedException | ExecutionException e) {
216 LOG.warn("Exception when getting Unique Id for key {}", nexthopKey, e);
220 protected List<ActionInfo> getEgressActionsForInterface(String ifName) {
221 List<ActionInfo> listActionInfo = new ArrayList<>();
223 Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
224 interfaceManager.getEgressActionsForInterface(
225 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build());
226 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
227 if (!rpcResult.isSuccessful()) {
228 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}",
229 ifName, rpcResult.getErrors());
231 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions =
232 rpcResult.getResult().getAction();
233 for (Action action : actions) {
234 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
235 actionClass = action.getAction();
236 if (actionClass instanceof OutputActionCase) {
237 listActionInfo.add(new ActionOutput(
238 ((OutputActionCase) actionClass).getOutputAction().getOutputNodeConnector()));
239 } else if (actionClass instanceof PushVlanActionCase) {
240 listActionInfo.add(new ActionPushVlan());
241 } else if (actionClass instanceof SetFieldCase) {
242 if (((SetFieldCase) actionClass).getSetField().getVlanMatch() != null) {
243 int vlanVid = ((SetFieldCase) actionClass).getSetField().getVlanMatch()
244 .getVlanId().getVlanId().getValue();
245 listActionInfo.add(new ActionSetFieldVlanVid(vlanVid));
247 } else if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
248 Short tableId = ((NxActionResubmitRpcAddGroupCase) actionClass).getNxResubmit().getTable();
249 listActionInfo.add(new ActionNxResubmit(action.getKey().getOrder() + 1, tableId));
250 } else if (actionClass instanceof NxActionRegLoadNodesNodeTableFlowApplyActionsCase) {
251 NxRegLoad nxRegLoad =
252 ((NxActionRegLoadNodesNodeTableFlowApplyActionsCase) actionClass).getNxRegLoad();
253 listActionInfo.add(new ActionRegLoad(action.getKey().getOrder() + 1, NxmNxReg6.class,
254 nxRegLoad.getDst().getStart(), nxRegLoad.getDst().getEnd(),
255 nxRegLoad.getValue().longValue()));
259 } catch (InterruptedException | ExecutionException e) {
260 LOG.warn("Exception when egress actions for interface {}", ifName, e);
262 return listActionInfo;
265 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
266 Class<? extends TunnelTypeBase> tunType = getReqTunType(getReqTransType().toUpperCase());
267 Future<RpcResult<GetTunnelInterfaceNameOutput>> result;
269 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
270 .setSourceDpid(srcDpId)
271 .setDestinationDpid(dstDpId)
272 .setTunnelType(tunType)
274 RpcResult<GetTunnelInterfaceNameOutput> rpcResult = result.get();
275 if (!rpcResult.isSuccessful()) {
276 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
278 return rpcResult.getResult().getInterfaceName();
280 } catch (InterruptedException | ExecutionException e) {
281 LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId, e);
286 protected String getTunnelInterfaceName(BigInteger srcDpId, org.opendaylight.yang.gen.v1.urn.ietf.params
287 .xml.ns.yang.ietf.inet.types.rev130715.IpAddress dstIp) {
288 Class<? extends TunnelTypeBase> tunType = getReqTunType(getReqTransType().toUpperCase());
289 Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> result;
291 result = itmManager.getInternalOrExternalInterfaceName(new GetInternalOrExternalInterfaceNameInputBuilder()
292 .setSourceDpid(srcDpId)
293 .setDestinationIp(dstIp)
294 .setTunnelType(tunType)
296 RpcResult<GetInternalOrExternalInterfaceNameOutput> rpcResult = result.get();
297 if (!rpcResult.isSuccessful()) {
298 LOG.warn("RPC Call to getTunnelInterfaceName returned with Errors {}", rpcResult.getErrors());
300 return rpcResult.getResult().getInterfaceName();
302 } catch (InterruptedException | ExecutionException e) {
303 LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstIp, e);
308 public long createLocalNextHop(long vpnId, BigInteger dpnId,
309 String ifName, String ipNextHopAddress, String ipPrefixAddress) {
310 String macAddress = FibUtil.getMacAddressFromPrefix(dataBroker, ifName, ipPrefixAddress);
311 String ipAddress = (macAddress != null) ? ipPrefixAddress : ipNextHopAddress;
313 long groupId = createNextHopPointer(getNextHopKey(vpnId, ipAddress));
315 LOG.error("Unable to allocate groupId for vpnId {} , prefix {}", vpnId, ipAddress);
318 String nextHopLockStr = vpnId + ipAddress;
319 synchronized (nextHopLockStr.intern()) {
320 VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress);
321 LOG.trace("nexthop: {} retrieved for vpnId {}, prefix {}, ifName {} on dpn {}", nexthop,
322 vpnId, ipAddress, ifName, dpnId);
323 if (nexthop == null) {
324 if (macAddress == null) {
325 macAddress = FibUtil.getMacAddressFromPrefix(dataBroker, ifName, ipAddress);
327 List<BucketInfo> listBucketInfo = new ArrayList<>();
328 List<ActionInfo> listActionInfo = new ArrayList<>();
330 if (macAddress != null) {
331 int actionKey = listActionInfo.size();
332 listActionInfo.add(new ActionSetFieldEthernetDestination(actionKey, new MacAddress(macAddress)));
333 //listActionInfo.add(0, new ActionPopMpls());
335 //FIXME: Log message here.
336 LOG.debug("mac address for new local nexthop is null");
338 listActionInfo.addAll(getEgressActionsForInterface(ifName));
339 BucketInfo bucket = new BucketInfo(listActionInfo);
341 listBucketInfo.add(bucket);
342 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
343 dpnId, groupId, ipAddress, GroupTypes.GroupAll, listBucketInfo);
344 LOG.trace("Install LNH Group: id {}, mac address {}, interface {} for prefix {}",
345 groupId, macAddress, ifName, ipAddress);
348 mdsalApiManager.syncInstallGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS);
350 LOG.info("Sleeping for {} to wait for the groups to get programmed.", waitTimeForSyncInstall);
351 Thread.sleep(waitTimeForSyncInstall);
352 } catch (InterruptedException error) {
353 LOG.warn("Error while waiting for group {} to install.", groupId);
354 LOG.debug("{}", error);
357 addVpnNexthopToDS(dpnId, vpnId, ipAddress, groupId);
360 //nexthop exists already; a new flow is going to point to it, increment the flowrefCount by 1
361 int flowrefCnt = nexthop.getFlowrefCount() + 1;
362 VpnNexthop nh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress))
363 .setFlowrefCount(flowrefCnt).build();
364 LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", nh, flowrefCnt);
365 syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress),
366 nh, DEFAULT_CALLBACK);
372 protected void addVpnNexthopToDS(BigInteger dpnId, long vpnId, String ipPrefix, long egressPointer) {
373 InstanceIdentifierBuilder<VpnNexthops> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
374 .child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
376 // Add nexthop to vpn node
377 VpnNexthop nh = new VpnNexthopBuilder()
378 .setKey(new VpnNexthopKey(ipPrefix))
380 .setIpAddress(ipPrefix)
382 .setEgressPointer(egressPointer).build();
384 InstanceIdentifier<VpnNexthop> id1 = idBuilder
385 .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)).build();
386 LOG.trace("Adding vpnnextHop {} to Operational DS", nh);
387 syncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
391 protected InstanceIdentifier<VpnNexthop> getVpnNextHopIdentifier(long vpnId, String ipAddress) {
392 InstanceIdentifier<VpnNexthop> id = InstanceIdentifier.builder(L3nexthop.class)
393 .child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).child(VpnNexthop.class,
394 new VpnNexthopKey(ipAddress)).build();
398 protected VpnNexthop getVpnNexthop(long vpnId, String ipAddress) {
400 // check if vpn node is there
401 InstanceIdentifierBuilder<VpnNexthops> idBuilder =
402 InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class,
403 new VpnNexthopsKey(vpnId));
404 InstanceIdentifier<VpnNexthops> id = idBuilder.build();
405 Optional<VpnNexthops> vpnNexthops = read(LogicalDatastoreType.OPERATIONAL, id);
406 if (vpnNexthops.isPresent()) {
407 // get nexthops list for vpn
408 List<VpnNexthop> nexthops = vpnNexthops.get().getVpnNexthop();
409 for (VpnNexthop nexthop : nexthops) {
410 if (nexthop.getIpAddress().equals(ipAddress)) {
412 LOG.trace("VpnNextHop : {}", nexthop);
416 // return null if not found
421 public AdjacencyResult getRemoteNextHopPointer(BigInteger remoteDpnId, long vpnId, String prefixIp,
423 String egressIfName = null;
424 LOG.trace("getRemoteNextHopPointer: input [remoteDpnId {}, vpnId {}, prefixIp {}, nextHopIp {} ]", remoteDpnId,
425 vpnId, prefixIp, nextHopIp);
427 Class<? extends InterfaceType> egressIfType;
428 ElanInstance elanInstance = getElanInstanceForPrefix(vpnId, prefixIp);
429 if (elanInstance != null) {
430 egressIfType = getInterfaceType(elanInstance);
432 LOG.warn("Failed to determine network type for prefixIp {} using tunnel", prefixIp);
433 egressIfType = Tunnel.class;
436 if (Tunnel.class.equals(egressIfType)) {
437 egressIfName = getTunnelRemoteNextHopPointer(remoteDpnId, nextHopIp);
439 egressIfName = getExtPortRemoteNextHopPointer(remoteDpnId, elanInstance);
442 LOG.trace("NextHop pointer for prefixIp {} vpnId {} dpnId {} is {}", prefixIp, vpnId, remoteDpnId,
444 return egressIfName != null ? new AdjacencyResult(egressIfName, egressIfType) : null;
447 public BigInteger getDpnForPrefix(long vpnId, String prefixIp) {
448 VpnNexthop vpnNexthop = getVpnNexthop(vpnId, prefixIp);
449 BigInteger localDpnId = (vpnNexthop == null) ? null : vpnNexthop.getDpnId();
453 private void removeVpnNexthopFromDS(long vpnId, String ipPrefix) {
455 InstanceIdentifierBuilder<VpnNexthop> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
456 .child(VpnNexthops.class, new VpnNexthopsKey(vpnId))
457 .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix));
458 InstanceIdentifier<VpnNexthop> id = idBuilder.build();
460 LOG.trace("Removing vpn next hop from datastore : {}", id);
461 syncDelete(LogicalDatastoreType.OPERATIONAL, id);
464 public void removeLocalNextHop(BigInteger dpnId, Long vpnId, String ipNextHopAddress, String ipPrefixAddress) {
465 String ipPrefixStr = vpnId + ipPrefixAddress;
466 VpnNexthop prefixNh = null;
467 synchronized (ipPrefixStr.intern()) {
468 prefixNh = getVpnNexthop(vpnId, ipPrefixAddress);
470 String ipAddress = (prefixNh != null) ? ipPrefixAddress : ipNextHopAddress;
472 String nextHopLockStr = vpnId + ipAddress;
473 synchronized (nextHopLockStr.intern()) {
474 VpnNexthop nh = getVpnNexthop(vpnId, ipAddress);
476 int newFlowrefCnt = nh.getFlowrefCount() - 1;
477 if (newFlowrefCnt == 0) { //remove the group only if there are no more flows using this group
478 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
479 dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupAll, null);
481 mdsalApiManager.removeGroup(groupEntity);
483 removeVpnNexthopFromDS(vpnId, ipAddress);
485 removeNextHopPointer(getNextHopKey(vpnId, ipAddress));
486 LOG.debug("Local Next hop {} for {} {} on dpn {} successfully deleted",
487 nh.getEgressPointer(), vpnId, ipAddress, dpnId);
489 //just update the flowrefCount of the vpnNexthop
490 VpnNexthop currNh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress))
491 .setFlowrefCount(newFlowrefCnt).build();
492 LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", currNh, newFlowrefCnt);
493 syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), currNh,
498 LOG.error("Local Next hop for {} on dpn {} not deleted", ipAddress, dpnId);
504 // TODO Clean up the exception handling
505 @SuppressWarnings("checkstyle:IllegalCatch")
506 private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
507 InstanceIdentifier<T> path) {
509 ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction();
511 Optional<T> result = Optional.absent();
513 result = tx.read(datastoreType, path).get();
514 } catch (Exception e) {
515 throw new RuntimeException(e);
521 private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
522 InstanceIdentifier<T> path, T data,
523 FutureCallback<Void> callback) {
524 WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
525 tx.merge(datastoreType, path, data, true);
526 Futures.addCallback(tx.submit(), callback);
529 private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
530 InstanceIdentifier<T> path, T data,
531 FutureCallback<Void> callback) {
532 WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
533 tx.merge(datastoreType, path, data, true);
534 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
537 } catch (InterruptedException | ExecutionException e) {
538 LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data, e);
539 throw new RuntimeException(e.getMessage());
543 private <T extends DataObject> void syncDelete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
544 WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
545 tx.delete(datastoreType, path);
546 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
549 } catch (InterruptedException | ExecutionException e) {
550 LOG.error("Error deleting from datastore (path) : ({})", path, e);
551 throw new RuntimeException(e.getMessage());
555 private InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
556 return InstanceIdentifier.builder(VpnInterfaces.class)
557 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
558 Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
561 InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
562 return InstanceIdentifier.builder(VpnInterfaces.class)
563 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
564 Adjacencies.class).build();
567 // TODO Clean up the console output
568 @SuppressWarnings("checkstyle:RegexpSinglelineJava")
569 public void setConfTransType(String service, String transportType) {
571 if (!service.toUpperCase().equals("L3VPN")) {
572 System.out.println("Please provide a valid service name. Available value(s): L3VPN");
573 LOG.error("Incorrect service {} provided for setting the transport type.", service);
577 L3VPNTransportTypes transType = L3VPNTransportTypes.validateTransportType(transportType.toUpperCase());
579 if (transType != L3VPNTransportTypes.Invalid) {
580 configuredTransportTypeL3VPN = transType;
584 public void writeConfTransTypeConfigDS() {
585 FibUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getConfTransportTypeIdentifier(),
586 createConfTransportType(configuredTransportTypeL3VPN.getTransportType()),
587 FibUtil.DEFAULT_CALLBACK);
590 public L3VPNTransportTypes getConfiguredTransportTypeL3VPN() {
591 return this.configuredTransportTypeL3VPN;
594 public String getReqTransType() {
595 if (configuredTransportTypeL3VPN == L3VPNTransportTypes.Invalid) {
597 * Restart scenario, Read from the ConfigDS.
598 * if the value is Unset, cache value as VxLAN.
600 LOG.trace("configureTransportType is not yet set.");
601 Optional<ConfTransportTypeL3vpn> configuredTransTypeFromConfig =
602 FibUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, getConfTransportTypeIdentifier());
604 if (configuredTransTypeFromConfig.isPresent()) {
605 if (configuredTransTypeFromConfig.get().getTransportType().equals(TunnelTypeGre.class)) {
606 configuredTransportTypeL3VPN.setL3VPNTransportTypes(ITMConstants.TUNNEL_TYPE_GRE);
608 configuredTransportTypeL3VPN.setL3VPNTransportTypes(ITMConstants.TUNNEL_TYPE_VXLAN);
610 LOG.trace("configuredTransportType set from config DS to {}",
611 getConfiguredTransportTypeL3VPN().getTransportType());
613 setConfTransType("L3VPN", L3VPNTransportTypes.VxLAN.getTransportType());
614 LOG.trace("configuredTransportType is not set in the Config DS. VxLAN as default will be used.");
617 LOG.trace("configuredTransportType is set as {}", getConfiguredTransportTypeL3VPN().getTransportType());
619 return getConfiguredTransportTypeL3VPN().getTransportType();
622 public InstanceIdentifier<ConfTransportTypeL3vpn> getConfTransportTypeIdentifier() {
623 return InstanceIdentifier.builder(ConfTransportTypeL3vpn.class).build();
626 private ConfTransportTypeL3vpn createConfTransportType(String type) {
627 ConfTransportTypeL3vpn confTransType;
629 case ITMConstants.TUNNEL_TYPE_GRE:
630 confTransType = new ConfTransportTypeL3vpnBuilder().setTransportType(TunnelTypeGre.class).build();
631 LOG.trace("Setting the confTransportType to GRE.");
633 case ITMConstants.TUNNEL_TYPE_VXLAN:
634 confTransType = new ConfTransportTypeL3vpnBuilder().setTransportType(TunnelTypeVxlan.class).build();
635 LOG.trace("Setting the confTransportType to VxLAN.");
638 LOG.trace("Invalid transport type {} passed to Config DS ", type);
639 confTransType = null;
642 return confTransType;
645 public Class<? extends TunnelTypeBase> getReqTunType(String transportType) {
646 switch (transportType) {
648 return TunnelTypeVxlan.class;
650 return TunnelTypeGre.class;
652 return TunnelTypeMplsOverGre.class;
656 public String getTransportTypeStr(String tunType) {
657 if (tunType.equals(TunnelTypeVxlan.class.toString())) {
658 return ITMConstants.TUNNEL_TYPE_VXLAN;
659 } else if (tunType.equals(TunnelTypeGre.class.toString())) {
660 return ITMConstants.TUNNEL_TYPE_GRE;
661 } else if (tunType.equals(TunnelTypeMplsOverGre.class.toString())) {
662 return ITMConstants.TUNNEL_TYPE_MPLSoGRE;
664 return ITMConstants.TUNNEL_TYPE_INVALID;
669 public void close() throws Exception {
670 LOG.info("{} close", getClass().getSimpleName());
673 // TODO Clean up the exception handling
674 @SuppressWarnings("checkstyle:IllegalCatch")
675 private String getTunnelRemoteNextHopPointer(BigInteger remoteDpnId, String nextHopIp) {
676 if (nextHopIp != null && !nextHopIp.isEmpty()) {
678 // here use the config for tunnel type param
679 return getTunnelInterfaceName(remoteDpnId,
680 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder
681 .getDefaultInstance(nextHopIp));
682 } catch (Exception ex) {
683 LOG.error("Error while retrieving nexthop pointer for nexthop {} : ", nextHopIp, ex);
690 private String getExtPortRemoteNextHopPointer(BigInteger remoteDpnId, ElanInstance elanInstance) {
691 return elanService.getExternalElanInterface(elanInstance.getElanInstanceName(), remoteDpnId);
695 * Get the interface type associated with the type of ELAN used for routing
696 * traffic to/from remote compute nodes.
698 * @param elanInstance The elan instance
699 * @return L2vlan for flat/VLAN network type and Tunnel otherwise
701 private Class<? extends InterfaceType> getInterfaceType(ElanInstance elanInstance) {
702 Class<? extends SegmentTypeBase> segmentType = elanInstance.getSegmentType();
703 if (SegmentTypeFlat.class.equals(segmentType) || SegmentTypeVlan.class.equals(segmentType)) {
710 private ElanInstance getElanInstanceForPrefix(long vpnId, String prefixIp) {
711 Prefixes prefix = FibUtil.getPrefixToInterface(dataBroker, vpnId, prefixIp);
712 if (prefix == null) {
713 LOG.warn("No prefix info was found for VPN id {} prefix {}", vpnId, prefixIp);
717 String interfaceName = prefix.getVpnInterfaceName();
718 if (interfaceName == null) {
719 LOG.warn("No VPN interface found for VPN id {} prefix {}", vpnId, prefixIp);
723 ElanInterface elanInterface = elanService.getElanInterfaceByElanInterfaceName(interfaceName);
724 if (elanInterface == null) {
725 LOG.warn("No ELAN interface found for VPN interface {} on VPN id {}", interfaceName, vpnId);
729 return elanService.getElanInstance(elanInterface.getElanInstanceName());
732 static class AdjacencyResult {
733 private String interfaceName;
734 private Class<? extends InterfaceType> interfaceType;
736 AdjacencyResult(String interfaceName, Class<? extends InterfaceType> interfaceType) {
737 this.interfaceName = interfaceName;
738 this.interfaceType = interfaceType;
741 public String getInterfaceName() {
742 return interfaceName;
745 public Class<? extends InterfaceType> getInterfaceType() {
746 return interfaceType;
750 public int hashCode() {
751 final int prime = 31;
753 result = prime * result + ((interfaceName == null) ? 0 : interfaceName.hashCode());
758 public boolean equals(Object obj) {
759 boolean result = false;
760 if (getClass() != obj.getClass()) {
763 AdjacencyResult other = (AdjacencyResult) obj;
764 result = interfaceName.equals(other.interfaceName);