2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.cloudservicechain;
10 import java.util.Optional;
11 import java.math.BigInteger;
12 import java.util.Collection;
13 import java.util.List;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.opendaylight.mdsal.binding.api.DataBroker;
18 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
19 import org.opendaylight.genius.mdsalutil.MDSALUtil;
20 import org.opendaylight.genius.mdsalutil.NWUtil;
21 import org.opendaylight.genius.mdsalutil.NwConstants;
22 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
23 import org.opendaylight.netvirt.cloudservicechain.utils.ElanServiceChainUtils;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev160711.ElanServiceChainState;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev160711.elan.to.pseudo.port.data.list.ElanToPseudoPortData;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * It is in charge of executing the changes in the Pipeline that are related to
37 * Elan Pseudo Ports when participating in ServiceChains.
41 public class ElanServiceChainHandler {
43 private static final Logger LOG = LoggerFactory.getLogger(ElanServiceChainHandler.class);
44 private final DataBroker broker;
45 private final IMdsalApiManager mdsalManager;
48 public ElanServiceChainHandler(final DataBroker db, final IMdsalApiManager mdsalMgr) {
50 this.mdsalManager = mdsalMgr;
54 * Programs the needed flows for sending traffic to the SCF pipeline when
55 * it is comming from an L2-GW (ELAN) and also for handing over that
56 * traffic from SCF to ELAN when the packets does not match any Service
59 * @param elanName Name of the ELAN to be considered
60 * @param tableId Table id, in the SCF Pipeline, to which the traffic must
62 * @param scfTag Tag of the ServiceChain
63 * @param elanLportTag LPortTag of the ElanPseudoPort that participates in
65 * @param addOrRemove States if the flows must be created or removed
67 public void programElanScfPipeline(String elanName, short tableId, long scfTag, int elanLportTag, int addOrRemove) {
68 LOG.info("programElanScfPipeline: elanName={} scfTag={} elanLportTag={} addOrRemove={}",
69 elanName, scfTag, elanLportTag, addOrRemove);
70 // There are 3 rules to be considered:
71 // 1. LportDispatcher To Scf. Matches on elanPseudoPort + SI=1. Goes to DL Subscriber table
72 // 2. LportDispatcher From Scf. Matches on elanPseudoPort + SI=3. Goes to ELAN DMAC
73 // 3. ExtTunnelTable From L2GwDevice. Matches on VNI + SI=1. Sets ElanPseudoPort tag and goes
74 // to LportDispatcher table.
75 // And these rules must be programmed in all the Elan footprint
77 // Find the ElanInstance
78 Optional<ElanInstance> elanInstance = ElanServiceChainUtils.getElanInstanceByName(broker, elanName);
79 if (!elanInstance.isPresent()) {
80 LOG.debug("Could not find an Elan Instance with name={}", elanName);
84 Collection<BigInteger> elanDpnsOpc = ElanServiceChainUtils.getElanDpnsByName(broker, elanName);
85 if (elanDpnsOpc.isEmpty()) {
86 LOG.debug("Could not find any DPN related to Elan {}", elanName);
90 // updates map which stores relationship between elan and elanLPortTag and scfTag
91 ElanServiceChainUtils.updateElanToLportTagMap(broker, elanName, elanLportTag, scfTag, addOrRemove);
93 Long vni = elanInstance.get().getSegmentationId();
95 LOG.warn("There is no VNI for elan {}. VNI is mandatory. Returning", elanName);
99 int elanTag = elanInstance.get().getElanTag().intValue();
100 LOG.debug("elanName={} -> vni={} elanTag={}", elanName, vni, elanTag);
101 // For each DPN in the Elan, do
102 // Program LPortDispatcher to Scf
103 // Program LPortDispatcher from Scf
104 // Program ExtTunnelTable.
105 for (BigInteger dpnId : elanDpnsOpc) {
106 ElanServiceChainUtils.programLPortDispatcherToScf(mdsalManager, dpnId, elanTag, elanLportTag, tableId,
107 scfTag, addOrRemove);
108 ElanServiceChainUtils.programLPortDispatcherFromScf(mdsalManager, dpnId, elanLportTag, elanTag,
110 ElanServiceChainUtils.programExternalTunnelTable(mdsalManager, dpnId, elanLportTag, vni, elanTag,
116 public void removeElanPseudoPortFlows(String elanName, int elanLportTag) {
117 Optional<ElanServiceChainState> elanServiceChainState =
118 ElanServiceChainUtils.getElanServiceChainState(broker, elanName);
119 if (!elanServiceChainState.isPresent()) {
120 LOG.warn("Could not find ServiceChain state data for Elan {}, elanPseudoLportTag={}",
121 elanName, elanLportTag);
124 Optional<ElanInstance> elanInstance = ElanServiceChainUtils.getElanInstanceByName(broker, elanName);
125 if (!elanInstance.isPresent()) {
126 LOG.warn("Could not find ElanInstance for name {}", elanName);
130 Long vni = elanInstance.get().getSegmentationId();
132 LOG.warn("Elan {} is not related to a VNI. VNI is mandatory for ServiceChaining. Returning", elanName);
136 List<ElanToPseudoPortData> elanToPseudoPortDataList = elanServiceChainState.get().getElanToPseudoPortData();
137 if (elanToPseudoPortDataList == null || elanToPseudoPortDataList.isEmpty()) {
138 LOG.info("Could not find elan {} with elanPseudoPort {} participating in any ServiceChain",
139 elanName, elanLportTag);
143 if (elanInstance.get().getElanTag() == null) {
144 LOG.info("Could not find elanTag for elan {} ", elanName);
148 int elanTag = elanInstance.get().getElanTag().intValue();
150 List<BigInteger> operativeDPNs = NWUtil.getOperativeDPNs(broker);
151 for (ElanToPseudoPortData elanToPseudoPortData : elanToPseudoPortDataList) {
152 Long scfTag = elanToPseudoPortData.getScfTag();
154 for (BigInteger dpnId : operativeDPNs) {
155 ElanServiceChainUtils.programLPortDispatcherToScf(mdsalManager, dpnId, elanTag, elanLportTag,
156 NwConstants.SCF_DOWN_SUB_FILTER_TCP_BASED_TABLE,
157 scfTag, NwConstants.DEL_FLOW);
158 ElanServiceChainUtils.programLPortDispatcherFromScf(mdsalManager, dpnId, elanLportTag, elanTag,
159 NwConstants.DEL_FLOW);
160 ElanServiceChainUtils.programExternalTunnelTable(mdsalManager, dpnId, elanLportTag, vni, elanTag,
161 NwConstants.DEL_FLOW);
165 // Lastly, remove the serviceChain-state for the Elan
166 InstanceIdentifier<ElanServiceChainState> path =
167 InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanName))
168 .augmentation(ElanServiceChainState.class)
171 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, path);