2 * Copyright (c) 2015 - 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.vpnservice.fibmanager;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
15 import java.math.BigInteger;
16 import java.net.InetAddress;
17 import java.net.UnknownHostException;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Future;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
26 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
27 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.vpnmanager.api.IVpnManager;
31 import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
32 import org.opendaylight.vpnservice.itm.globals.ITMConstants;
33 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
34 import org.opendaylight.vpnservice.mdsalutil.ActionType;
35 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
36 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
37 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
38 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
39 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
40 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
41 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
42 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
43 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnToExtraroute;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeMplsOverGre;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetTunnelTypeInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetTunnelTypeOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
74 import org.opendaylight.yangtools.concepts.ListenerRegistration;
75 import org.opendaylight.yangtools.yang.binding.DataObject;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
77 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
78 import org.opendaylight.yangtools.yang.common.RpcResult;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
82 public class FibManager extends AbstractDataChangeListener<VrfEntry> implements AutoCloseable{
83 private static final Logger LOG = LoggerFactory.getLogger(FibManager.class);
84 private static final String FLOWID_PREFIX = "L3.";
85 private ListenerRegistration<DataChangeListener> listenerRegistration;
86 private final DataBroker broker;
87 private IMdsalApiManager mdsalManager;
88 private IVpnManager vpnmanager;
89 private NexthopManager nextHopManager;
90 private ItmRpcService itmManager;
91 private OdlInterfaceRpcService interfaceManager;
92 private static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);
93 private static final BigInteger COOKIE_VM_FIB_TABLE = new BigInteger("8000003", 16);
94 private static final int DEFAULT_FIB_FLOW_PRIORITY = 10;
95 private static final BigInteger METADATA_MASK_CLEAR = new BigInteger("000000FFFFFFFFFF", 16);
96 private static final BigInteger CLEAR_METADATA = BigInteger.valueOf(0);
97 public static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
100 public FibManager(final DataBroker db) {
101 super(VrfEntry.class);
103 registerListener(db);
107 public void close() throws Exception {
108 if (listenerRegistration != null) {
110 listenerRegistration.close();
111 } catch (final Exception e) {
112 LOG.error("Error when cleaning up DataChangeListener.", e);
114 listenerRegistration = null;
116 LOG.info("Fib Manager Closed");
119 public void setNextHopManager(NexthopManager nextHopManager) {
120 this.nextHopManager = nextHopManager;
123 public void setMdsalManager(IMdsalApiManager mdsalManager) {
124 this.mdsalManager = mdsalManager;
127 public void setVpnmanager(IVpnManager vpnmanager) {
128 this.vpnmanager = vpnmanager;
131 public void setITMRpcService(ItmRpcService itmManager) {
132 this.itmManager = itmManager;
135 public void setInterfaceManager(OdlInterfaceRpcService ifManager) {
136 this.interfaceManager = ifManager;
139 private void registerListener(final DataBroker db) {
141 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
142 getWildCardPath(), FibManager.this, DataChangeScope.SUBTREE);
143 } catch (final Exception e) {
144 LOG.error("FibManager DataChange listener registration fail!", e);
145 throw new IllegalStateException("FibManager registration Listener failed.", e);
150 private InstanceIdentifier<VrfEntry> getWildCardPath() {
151 return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class).child(VrfEntry.class);
156 protected void add(final InstanceIdentifier<VrfEntry> identifier,
157 final VrfEntry vrfEntry) {
158 LOG.trace("key: " + identifier + ", value=" + vrfEntry );
159 createFibEntries(identifier, vrfEntry);
163 protected void remove(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry) {
164 LOG.trace("key: " + identifier + ", value=" + vrfEntry);
165 deleteFibEntries(identifier, vrfEntry);
169 protected void update(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update) {
170 LOG.trace("key: " + identifier + ", original=" + original + ", update=" + update );
171 createFibEntries(identifier, update);
174 private void createFibEntries(final InstanceIdentifier<VrfEntry> identifier,
175 final VrfEntry vrfEntry) {
176 final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
177 Preconditions.checkNotNull(vrfTableKey, "VrfTablesKey cannot be null or empty!");
178 Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
180 VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
181 Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available!");
182 Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId() + "has null vpnId!");
184 Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
185 BigInteger localDpnId = createLocalFibEntry(vpnInstance.getVpnId(),
186 vrfTableKey.getRouteDistinguisher(), vrfEntry);
187 if (vpnToDpnList != null) {
188 for (VpnToDpnList curDpn : vpnToDpnList) {
189 if (!curDpn.getDpnId().equals(localDpnId)) {
190 createRemoteFibEntry(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(),
191 vrfTableKey, vrfEntry);
197 public BigInteger createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
198 BigInteger localDpnId = BigInteger.ZERO;
199 Prefixes localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
200 String localNextHopIP = vrfEntry.getDestPrefix();
202 if(localNextHopInfo == null) {
203 //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
204 Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
205 if (extra_route != null) {
206 localNextHopInfo = getPrefixToInterface(vpnId, extra_route.getNexthopIp() + "/32");
207 localNextHopIP = extra_route.getNexthopIp() + "/32";
211 if(localNextHopInfo != null) {
212 localDpnId = localNextHopInfo.getDpnId();
213 long groupId = nextHopManager.createLocalNextHop(vpnId, localDpnId, localNextHopInfo.getVpnInterfaceName(), localNextHopIP);
214 List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
216 actionInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
218 makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, actionInfos, NwConstants.ADD_FLOW);
219 makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), groupId, vrfEntry.getNextHopAddress(), NwConstants.ADD_FLOW);
221 LOG.debug("Installing tunnel table entry on dpn {} for interface {} with label {}",
222 localDpnId, localNextHopInfo.getVpnInterfaceName(), vrfEntry.getLabel());
223 makeTunnelTableEntry(localDpnId, vrfEntry.getLabel(), groupId);
229 private void makeTunnelTableEntry(BigInteger dpId, long label, long groupId/*String egressInterfaceName*/) {
230 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
231 actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
234 createTerminatingServiceActions(dpId, (int)label, actionsInfos);
236 LOG.debug("Terminating service Entry for dpID {} : label : {} egress : {} installed successfully {}",
237 dpId, label, groupId);
240 public void createTerminatingServiceActions( BigInteger destDpId, int label, List<ActionInfo> actionsInfos) {
241 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
243 LOG.info("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", destDpId , label,actionsInfos);
246 // FIXME vxlan vni bit set is not working properly with OVS.need to revisit
247 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(label)}));
249 List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
250 mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
252 FlowEntity terminatingServiceTableFlowEntity = MDSALUtil.buildFlowEntity(destDpId, NwConstants.INTERNAL_TUNNEL_TABLE,
253 getFlowRef(destDpId, NwConstants.INTERNAL_TUNNEL_TABLE,label), 5, String.format("%s:%d","TST Flow Entry ",label),
254 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(label)),mkMatches, mkInstructions);
256 mdsalManager.installFlow(terminatingServiceTableFlowEntity);
259 private void removeTunnelTableEntry(BigInteger dpId, long label) {
260 FlowEntity flowEntity;
261 LOG.info("remove terminatingServiceActions called with DpnId = {} and label = {}", dpId , label);
262 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
264 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(label)}));
265 flowEntity = MDSALUtil.buildFlowEntity(dpId,
266 NwConstants.INTERNAL_TUNNEL_TABLE,
267 getFlowRef(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, (int)label),
268 5, String.format("%s:%d","TST Flow Entry ",label), 0, 0,
269 COOKIE_TUNNEL.add(BigInteger.valueOf(label)), mkMatches, null);
270 mdsalManager.removeFlow(flowEntity);
271 LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}",dpId, label);
274 public BigInteger deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
275 BigInteger localDpnId = BigInteger.ZERO;
276 boolean isExtraRoute = false;
277 VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
278 String localNextHopIP = vrfEntry.getDestPrefix();
280 if(localNextHopInfo == null) {
281 //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
282 Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
283 if (extra_route != null) {
284 localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp() + "/32");
285 localNextHopIP = extra_route.getNexthopIp() + "/32";
291 if(localNextHopInfo != null) {
292 localDpnId = localNextHopInfo.getDpnId();
293 Prefixes prefix = getPrefixToInterface(vpnId, isExtraRoute ? localNextHopIP : vrfEntry.getDestPrefix());
294 makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, null /* invalid */,
295 NwConstants.DEL_FLOW);
296 makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), 0 /* invalid */,
297 vrfEntry.getNextHopAddress(), NwConstants.DEL_FLOW);
298 removeTunnelTableEntry(localDpnId, vrfEntry.getLabel());
299 deleteLocalAdjacency(localDpnId, vpnId, localNextHopIP);
304 private InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(Long vpnId, String ipPrefix) {
305 return InstanceIdentifier.builder(PrefixToInterface.class)
306 .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
309 private Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
310 Optional<Prefixes> localNextHopInfoData =
311 FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
312 return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
315 private InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
316 return InstanceIdentifier.builder(VpnToExtraroute.class)
317 .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
318 new ExtrarouteKey(ipPrefix)).build();
321 private Extraroute getVpnToExtraroute(String rd, String ipPrefix) {
322 Optional<Extraroute> extraRouteInfo =
323 FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, getVpnToExtrarouteIdentifier(rd, ipPrefix));
324 return extraRouteInfo.isPresent() ? extraRouteInfo.get() : null;
328 private Class<? extends TunnelTypeBase> getTunnelType(String ifName) {
330 Future<RpcResult<GetTunnelTypeOutput>> result = interfaceManager.getTunnelType(
331 new GetTunnelTypeInputBuilder().setIntfName(ifName).build());
332 RpcResult<GetTunnelTypeOutput> rpcResult = result.get();
333 if(!rpcResult.isSuccessful()) {
334 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
336 return rpcResult.getResult().getTunnelType();
339 } catch (InterruptedException | ExecutionException e) {
340 LOG.warn("Exception when getting tunnel interface Id for tunnel type {}", e);
346 private void createRemoteFibEntry(final BigInteger localDpnId, final BigInteger remoteDpnId,
347 final long vpnId, final VrfTablesKey vrfTableKey,
348 final VrfEntry vrfEntry) {
349 String rd = vrfTableKey.getRouteDistinguisher();
350 LOG.debug("adding route " + vrfEntry.getDestPrefix() + " " + rd);
351 /********************************************/
352 String tunnelInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry, rd);
353 if(tunnelInterface == null) {
354 LOG.error("Could not get interface for nexthop: {} in vpn {}",
355 vrfEntry.getNextHopAddress(), rd);
356 LOG.warn("Failed to add Route: {} in vpn: {}",
357 vrfEntry.getDestPrefix(), rd);
360 List<ActionInfo> actionInfos = new ArrayList<>();
361 Class<? extends TunnelTypeBase> tunnel_type = getTunnelType(tunnelInterface);
362 if (tunnel_type.equals(TunnelTypeMplsOverGre.class)) {
363 LOG.debug("Push label action for prefix {}", vrfEntry.getDestPrefix());
364 actionInfos.add(new ActionInfo(ActionType.push_mpls, new String[] { null }));
365 actionInfos.add(new ActionInfo(ActionType.set_field_mpls_label, new String[] { Long.toString(vrfEntry.getLabel())}));
367 int label = vrfEntry.getLabel().intValue();
369 // FIXME vxlan vni bit set is not working properly with OVS.need to revisit
370 if(tunnel_type.equals(TunnelTypeVxlan.class)) {
371 tunnelId = BigInteger.valueOf(label);
373 tunnelId = BigInteger.valueOf(label);
375 LOG.debug("adding set tunnel id action for label {}", label);
376 actionInfos.add(new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[]{
379 actionInfos.addAll(nextHopManager.getEgressActionsForInterface(tunnelInterface));
381 List<ActionInfo> actionInfos = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
382 if(actionInfos == null) {
383 LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
384 vrfEntry.getNextHopAddress(), rd);
385 LOG.warn("Failed to add Route: {} in vpn: {}",
386 vrfEntry.getDestPrefix(), rd);
389 BigInteger dpnId = nextHopManager.getDpnForPrefix(vpnId, vrfEntry.getDestPrefix());
391 //This route may be extra route... try to query with nexthop Ip
392 LOG.debug("Checking for extra route to install remote fib entry {}", vrfEntry.getDestPrefix());
393 dpnId = nextHopManager.getDpnForPrefix(vpnId, vrfEntry.getNextHopAddress() + "/32");
396 LOG.debug("Push label action for prefix {}", vrfEntry.getDestPrefix());
397 actionInfos.add(new ActionInfo(ActionType.push_mpls, new String[] { null }));
398 actionInfos.add(new ActionInfo(ActionType.set_field_mpls_label, new String[] { Long.toString(vrfEntry.getLabel())}));
400 int label = vrfEntry.getLabel().intValue();
401 LOG.debug("adding set tunnel id action for label {}", label);
402 actionInfos.add(new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
403 MetaDataUtil.getTunnelIdWithValidVniBitAndVniSet(label),
404 MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
407 makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, actionInfos, NwConstants.ADD_FLOW);
409 "Successfully added fib entry for " + vrfEntry.getDestPrefix() + " vpnId " + vpnId);
412 private void delIntfFromDpnToVpnList(long vpnId, BigInteger dpnId, String intfName, String rd) {
413 InstanceIdentifier<VpnToDpnList> id = FibUtil.getVpnToDpnListIdentifier(rd, dpnId);
414 Optional<VpnToDpnList> dpnInVpn = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
415 if (dpnInVpn.isPresent()) {
416 List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
417 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
418 org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
419 currVpnInterface = new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder().setInterfaceName(intfName).build();
421 if (vpnInterfaces.remove(currVpnInterface)) {
422 if (vpnInterfaces.isEmpty()) {
423 LOG.trace("Last vpn interface {} on dpn {} for vpn {}. Clean up fib in dpn", intfName, dpnId, rd);
424 FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id);
425 cleanUpDpnForVpn(dpnId, vpnId, rd);
427 LOG.trace("Delete vpn interface {} from dpn {} to vpn {} list.", intfName, dpnId, rd);
428 FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
429 org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
430 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
431 new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(intfName)));
437 private void cleanUpOpDataForFib(Long vpnId, String rd, final VrfEntry vrfEntry) {
438 /* Get interface info from prefix to interface mapping;
439 Use the interface info to get the corresponding vpn interface op DS entry,
440 remove the adjacency corresponding to this fib entry.
441 If adjacency removed is the last adjacency, clean up the following:
442 - vpn interface from dpntovpn list, dpn if last vpn interface on dpn
443 - prefix to interface entry
444 - vpn interface op DS
446 Prefixes prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
447 Extraroute extraRoute = null;
448 if (prefixInfo == null) {
449 extraRoute = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
450 if(extraRoute != null) {
451 prefixInfo = getPrefixToInterface(vpnId, extraRoute.getNexthopIp() + "/32");
452 //clean up the vpn to extra route entry in DS
453 FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getVpnToExtrarouteIdentifier(rd, vrfEntry.getDestPrefix()));
456 if (prefixInfo == null) {
457 LOG.debug("Cleanup VPN Data Failed as unable to find prefix Info for " + vrfEntry.getDestPrefix());
458 return; //Don't have any info for this prefix (shouldn't happen); need to return
460 String ifName = prefixInfo.getVpnInterfaceName();
461 Optional<Adjacencies> optAdjacencies = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjListPath(ifName));
463 if (optAdjacencies.isPresent()) {
464 numAdj = optAdjacencies.get().getAdjacency().size();
466 LOG.trace("cleanUpOpDataForFib: remove adjacency for prefix: {} {}", vpnId, vrfEntry.getDestPrefix());
467 //remove adjacency corr to prefix
469 FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
470 FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
473 if ((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
474 //clean up the vpn interface from DpnToVpn list
475 LOG.trace("Clean up vpn interface {} from dpn {} to vpn {} list.", ifName, prefixInfo.getDpnId(), rd);
476 FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
477 FibUtil.getVpnInterfaceIdentifier(ifName));
481 private void deleteFibEntries(final InstanceIdentifier<VrfEntry> identifier,
482 final VrfEntry vrfEntry) {
483 final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
484 Preconditions.checkNotNull(vrfTableKey, "VrfTablesKey cannot be null or empty!");
485 Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
487 VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
488 Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available!");
489 Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
490 BigInteger localDpnId = deleteLocalFibEntry(vpnInstance.getVpnId(),
491 vrfTableKey.getRouteDistinguisher(), vrfEntry);
492 if (vpnToDpnList != null) {
493 for (VpnToDpnList curDpn : vpnToDpnList) {
494 if (!curDpn.getDpnId().equals(localDpnId)) {
495 deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry);
499 //The flow/group entry has been deleted from config DS; need to clean up associated operational
500 //DS entries in VPN Op DS, VpnInstanceOpData and PrefixToInterface to complete deletion
501 cleanUpOpDataForFib(vpnInstance.getVpnId(), vrfTableKey.getRouteDistinguisher(), vrfEntry);
504 public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
505 final long vpnId, final VrfTablesKey vrfTableKey,
506 final VrfEntry vrfEntry) {
507 LOG.debug("deleting route "+ vrfEntry.getDestPrefix() + " "+vpnId);
508 String rd = vrfTableKey.getRouteDistinguisher();
509 boolean isRemoteRoute = true;
510 if (localDpnId == null) {
511 // localDpnId is not known when clean up happens for last vm for a vpn on a dpn
512 VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
513 if(localNextHopInfo == null) {
514 //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
515 Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
516 if (extra_route != null) {
517 localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp());
520 if (localNextHopInfo != null) {
521 isRemoteRoute = (!remoteDpnId.equals(localNextHopInfo.getDpnId()));
525 makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW);
526 LOG.debug("Successfully delete fib entry for "+ vrfEntry.getDestPrefix() + " vpnId "+vpnId);
528 LOG.debug("Did not delete fib entry rd: {} =, prefix: {} as it is local to dpn {}", rd, vrfEntry.getDestPrefix(), remoteDpnId);
532 private long getIpAddress(byte[] rawIpAddress) {
533 return (((rawIpAddress[0] & 0xFF) << (3 * 8)) + ((rawIpAddress[1] & 0xFF) << (2 * 8))
534 + ((rawIpAddress[2] & 0xFF) << (1 * 8)) + (rawIpAddress[3] & 0xFF)) & 0xffffffffL;
537 private void makeConnectedRoute(BigInteger dpId, long vpnId, VrfEntry vrfEntry, String rd,
538 List<ActionInfo> actionInfos, int addOrRemove) {
539 LOG.trace("makeConnectedRoute: vrfEntry {}",vrfEntry);
540 String values[] = vrfEntry.getDestPrefix().split("/");
541 String ipAddress = values[0];
542 int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
543 LOG.debug("Adding route to DPN. ip {} masklen {}", ipAddress, prefixLength);
544 InetAddress destPrefix = null;
546 destPrefix = InetAddress.getByName(ipAddress);
547 } catch (UnknownHostException e) {
548 LOG.error("UnknowHostException in addRoute. Failed to add Route for ipPrefix {}", vrfEntry.getDestPrefix());
552 List<MatchInfo> matches = new ArrayList<MatchInfo>();
554 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
555 BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
557 matches.add(new MatchInfo(MatchFieldType.eth_type,
558 new long[] { 0x0800L }));
560 if(prefixLength != 0) {
561 matches.add(new MatchInfo(MatchFieldType.ipv4_dst, new long[] {
562 getIpAddress(destPrefix.getAddress()), prefixLength }));
565 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
566 if(addOrRemove == NwConstants.ADD_FLOW) {
567 instructions.add(new InstructionInfo(InstructionType.write_actions, actionInfos));
570 String flowRef = getFlowRef(dpId, NwConstants.L3_FIB_TABLE, rd, destPrefix);
572 FlowEntity flowEntity;
574 int priority = DEFAULT_FIB_FLOW_PRIORITY + prefixLength;
575 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
576 priority, flowRef, 0, 0,
577 COOKIE_VM_FIB_TABLE, matches, instructions);
579 if (addOrRemove == NwConstants.ADD_FLOW) {
580 /* We need to call sync API to install flow so that 2 DS operations on the same object do not
581 * happen at same time. However, MDSALManager's syncInstallFlow takes a delay time (or uses a default one) to wait
582 * for or for notification that operational DS write for flows is done. We do not turn on the stats writing for flows,
583 * so that notification never comes, so we do not need that wait. Sending the lowest value of wait "1 ms" since 0 wait means
584 * wait indefinitely. */
585 mdsalManager.syncInstallFlow(flowEntity, 1);
587 mdsalManager.syncRemoveFlow(flowEntity, 1);
591 private void makeLFibTableEntry(BigInteger dpId, long label, long groupId,
592 String nextHop, int addOrRemove) {
593 List<MatchInfo> matches = new ArrayList<MatchInfo>();
594 matches.add(new MatchInfo(MatchFieldType.eth_type,
595 new long[] { 0x8847L }));
596 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(label)}));
598 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
599 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
600 actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
601 actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
602 instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
604 // Install the flow entry in L3_LFIB_TABLE
605 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, label, nextHop);
607 FlowEntity flowEntity;
608 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_LFIB_TABLE, flowRef,
609 DEFAULT_FIB_FLOW_PRIORITY, flowRef, 0, 0,
610 COOKIE_VM_LFIB_TABLE, matches, instructions);
612 if (addOrRemove == NwConstants.ADD_FLOW) {
613 /* We need to call sync API to install flow so that 2 DS operations on the same object do not
614 * happen at same time. However, MDSALManager's syncInstallFlow takes a delay time (or uses a default one) to wait
615 * for or for notification that operational DS write for flows is done. We do not turn on the stats writing for flows,
616 * so that notification never comes, so we do not need that wait. Sending the lowest value of wait "1 ms" since 0 wait means
617 * wait indefinitely. */
619 mdsalManager.syncInstallFlow(flowEntity, 1);
621 mdsalManager.syncRemoveFlow(flowEntity, 1);
623 LOG.debug("LFIB Entry for dpID {} : label : {} group {} modified successfully {}",dpId, label, groupId );
626 private void deleteLocalAdjacency(final BigInteger dpId, final long vpnId, final String ipAddress) {
627 LOG.trace("deleteLocalAdjacency called with dpid {}, vpnId{}, ipAddress {}",dpId, vpnId, ipAddress);
629 nextHopManager.removeLocalNextHop(dpId, vpnId, ipAddress);
630 } catch (NullPointerException e) {
635 public void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd) {
636 LOG.trace("New dpn {} for vpn {} : populateFibOnNewDpn", dpnId, rd);
637 InstanceIdentifier<VrfTables> id = buildVrfId(rd);
638 String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
639 synchronized (lockOnDpnVpn.intern()) {
640 Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
641 if (vrfTable.isPresent()) {
642 for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
643 // Passing null as we don't know the dpn
644 // to which prefix is attached at this point
645 createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
651 public void populateFibOnDpn(BigInteger dpnId, long vpnId, String rd, String nexthopIp) {
652 LOG.trace("dpn {} for vpn {}, nexthopIp {} : populateFibOnDpn", dpnId, rd, nexthopIp);
653 InstanceIdentifier<VrfTables> id = buildVrfId(rd);
654 String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
655 synchronized (lockOnDpnVpn.intern()) {
656 Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
657 if (vrfTable.isPresent()) {
658 for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
659 // Passing null as we don't know the dpn
660 // to which prefix is attached at this point
661 if (nexthopIp == vrfEntry.getNextHopAddress()) {
662 createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
669 public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd) {
670 LOG.trace("Remove dpn {} for vpn {} : cleanUpDpnForVpn", dpnId, rd);
671 InstanceIdentifier<VrfTables> id = buildVrfId(rd);
672 String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
673 synchronized (lockOnDpnVpn.intern()) {
674 Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
675 if (vrfTable.isPresent()) {
676 for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
677 // Passing null as we don't know the dpn
678 // to which prefix is attached at this point
679 deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
685 public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd, String nexthopIp) {
686 LOG.trace("dpn {} for vpn {}, nexthopIp {} : cleanUpDpnForVpn", dpnId, rd, nexthopIp);
687 InstanceIdentifier<VrfTables> id = buildVrfId(rd);
688 String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
689 synchronized (lockOnDpnVpn.intern()) {
690 Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
691 if (vrfTable.isPresent()) {
692 for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
693 // Passing null as we don't know the dpn
694 // to which prefix is attached at this point
695 if (nexthopIp == vrfEntry.getNextHopAddress()) {
696 deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
703 public static InstanceIdentifier<VrfTables> buildVrfId(String rd) {
704 InstanceIdentifierBuilder<VrfTables> idBuilder =
705 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
706 InstanceIdentifier<VrfTables> id = idBuilder.build();
710 private String getFlowRef(BigInteger dpnId, short tableId, long label, String nextHop) {
711 return new StringBuilder(64).append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
712 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
713 .append(label).append(NwConstants.FLOWID_SEPARATOR)
714 .append(nextHop).toString();
717 private String getFlowRef(BigInteger dpnId, short tableId, String rd, InetAddress destPrefix) {
718 return new StringBuilder(64).append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
719 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
720 .append(rd).append(NwConstants.FLOWID_SEPARATOR)
721 .append(destPrefix.getHostAddress()).toString();
724 protected String resolveAdjacency(final BigInteger localDpnId, final BigInteger remoteDpnId,
725 final long vpnId, final VrfEntry vrfEntry, String rd) {
726 String adjacency = null;
727 boolean staticRoute = false;
728 LOG.trace("resolveAdjacency called with localdpid{} remotedpid {}, vpnId{}, VrfEntry {}", localDpnId, remoteDpnId, vpnId, vrfEntry);
730 Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
731 if(extra_route != null) {
736 nextHopManager.getRemoteNextHopPointer(localDpnId, remoteDpnId, vpnId,
737 (staticRoute == true) ? extra_route.getNexthopIp() + "/32" : vrfEntry.getDestPrefix(),
738 vrfEntry.getNextHopAddress());
739 } catch (NullPointerException e) {
745 protected VpnInstanceOpDataEntry getVpnInstance(String rd) {
746 InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.create(VpnInstanceOpData.class).child(
747 VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd));
748 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
749 if(vpnInstanceOpData.isPresent()) {
750 return vpnInstanceOpData.get();
755 public void processNodeAdd(BigInteger dpnId) {
756 LOG.debug("Received notification to install TableMiss entries for dpn {} ", dpnId);
757 makeTableMissFlow(dpnId, NwConstants.ADD_FLOW);
758 makeL3IntfTblMissFlow(dpnId, NwConstants.ADD_FLOW);
761 private void makeTableMissFlow(BigInteger dpnId, int addOrRemove) {
762 final BigInteger COOKIE_TABLE_MISS = new BigInteger("1030000", 16);
763 // Instruction to goto L3 InterfaceTable
764 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
765 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.L3_INTERFACE_TABLE }));
766 List<MatchInfo> matches = new ArrayList<MatchInfo>();
767 FlowEntity flowEntityLfib = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_LFIB_TABLE,
768 getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, NwConstants.TABLE_MISS_FLOW),
769 NwConstants.TABLE_MISS_PRIORITY, "Table Miss", 0, 0, COOKIE_TABLE_MISS, matches, instructions);
771 FlowEntity flowEntityFib = MDSALUtil.buildFlowEntity(dpnId,NwConstants.L3_FIB_TABLE, getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, NwConstants.TABLE_MISS_FLOW),
772 NwConstants.TABLE_MISS_PRIORITY, "FIB Table Miss Flow", 0, 0, COOKIE_VM_FIB_TABLE,
773 matches, instructions);
775 if (addOrRemove == NwConstants.ADD_FLOW) {
776 LOG.debug("Invoking MDSAL to install Table Miss Entries");
777 mdsalManager.installFlow(flowEntityLfib);
778 mdsalManager.installFlow(flowEntityFib);
780 mdsalManager.removeFlow(flowEntityLfib);
781 mdsalManager.removeFlow(flowEntityFib);
786 private String getFlowRef(BigInteger dpnId, short tableId, int tableMiss) {
787 return new StringBuffer().append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
788 .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(tableMiss)
789 .append(FLOWID_PREFIX).toString();
793 * Install flow entry in protocol table to forward mpls
794 * coming through gre tunnel to LFIB table.
796 private void makeProtocolTableFlow(BigInteger dpnId, int addOrRemove) {
797 final BigInteger COOKIE_PROTOCOL_TABLE = new BigInteger("1070000", 16);
798 // Instruction to goto L3 InterfaceTable
799 List<InstructionInfo> instructions = new ArrayList<>();
800 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {NwConstants.L3_LFIB_TABLE}));
801 List<MatchInfo> matches = new ArrayList<MatchInfo>();
802 matches.add(new MatchInfo(MatchFieldType.eth_type,
803 new long[] { 0x8847L }));
804 FlowEntity flowEntityToLfib = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_PROTOCOL_TABLE,
805 getFlowRef(dpnId, NwConstants.L3_PROTOCOL_TABLE,
806 NwConstants.L3_LFIB_TABLE),
807 DEFAULT_FIB_FLOW_PRIORITY,
808 "Protocol Table For LFIB",
810 COOKIE_PROTOCOL_TABLE,
811 matches, instructions);
813 if (addOrRemove == NwConstants.ADD_FLOW) {
814 LOG.debug("Invoking MDSAL to install Protocol Entries for dpn {}", dpnId);
815 mdsalManager.installFlow(flowEntityToLfib);
817 mdsalManager.removeFlow(flowEntityToLfib);
821 public List<String> printFibEntries() {
822 List<String> result = new ArrayList<String>();
823 result.add(String.format(" %-7s %-20s %-20s %-7s", "RD", "Prefix", "Nexthop", "Label"));
824 result.add("-------------------------------------------------------------------");
825 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
826 Optional<FibEntries> fibEntries = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
827 if (fibEntries.isPresent()) {
828 List<VrfTables> vrfTables = fibEntries.get().getVrfTables();
829 for (VrfTables vrfTable : vrfTables) {
830 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
831 result.add(String.format(" %-7s %-20s %-20s %-7s", vrfTable.getRouteDistinguisher(),
832 vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddress(), vrfEntry.getLabel()));
839 private void makeL3IntfTblMissFlow(BigInteger dpnId, int addOrRemove) {
840 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
841 List<MatchInfo> matches = new ArrayList<MatchInfo>();
842 final BigInteger COOKIE_TABLE_MISS = new BigInteger("1030000", 16);
843 // Instruction to clear metadata except SI and LportTag bits
844 instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] {
845 CLEAR_METADATA, METADATA_MASK_CLEAR }));
846 // Instruction to clear action
847 instructions.add(new InstructionInfo(InstructionType.clear_actions));
848 // Instruction to goto L3 InterfaceTable
850 List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
851 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
852 Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
853 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
854 //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
856 FlowEntity flowEntityL3Intf = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_INTERFACE_TABLE,
857 getFlowRef(dpnId, NwConstants.L3_INTERFACE_TABLE, NwConstants.TABLE_MISS_FLOW),
858 NwConstants.TABLE_MISS_PRIORITY, "L3 Interface Table Miss", 0, 0, COOKIE_TABLE_MISS, matches, instructions);
859 if (addOrRemove == NwConstants.ADD_FLOW) {
860 LOG.info("Invoking MDSAL to install L3 interface Table Miss Entries");
861 mdsalManager.installFlow(flowEntityL3Intf);
863 mdsalManager.removeFlow(flowEntityL3Intf);