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 com.google.common.base.Optional;
11 import java.math.BigInteger;
12 import java.util.Collection;
13 import java.util.List;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.mdsalutil.MDSALUtil;
18 import org.opendaylight.genius.mdsalutil.NWUtil;
19 import org.opendaylight.genius.mdsalutil.NwConstants;
20 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
21 import org.opendaylight.netvirt.cloudservicechain.utils.ElanServiceChainUtils;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev170511.ElanServiceChainState;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev170511.elan.to.pseudo.port.data.list.ElanToPseudoPortData;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 * It is in charge of executing the changes in the Pipeline that are related to
35 * Elan Pseudo Ports when participating in ServiceChains.
38 public class ElanServiceChainHandler {
40 private static final Logger LOG = LoggerFactory.getLogger(ElanServiceChainHandler.class);
42 private final DataBroker broker;
43 private final IMdsalApiManager mdsalManager;
46 public ElanServiceChainHandler(final DataBroker db, final IMdsalApiManager mdsalMgr) {
48 this.mdsalManager = mdsalMgr;
52 * Programs the needed flows for sending traffic to the SCF pipeline when
53 * it is comming from an L2-GW (ELAN) and also for handing over that
54 * traffic from SCF to ELAN when the packets does not match any Service
57 * @param elanName Name of the ELAN to be considered
58 * @param tableId Table id, in the SCF Pipeline, to which the traffic must
60 * @param scfTag Tag of the ServiceChain
61 * @param elanLportTag LPortTag of the ElanPseudoPort that participates in
63 * @param addOrRemove States if the flows must be created or removed
65 public void programElanScfPipeline(String elanName, short tableId, long scfTag, int elanLportTag, int addOrRemove) {
66 LOG.info("programElanScfPipeline: elanName={} scfTag={} elanLportTag={} addOrRemove={}",
67 elanName, scfTag, elanLportTag, addOrRemove);
68 // There are 3 rules to be considered:
69 // 1. LportDispatcher To Scf. Matches on elanPseudoPort + SI=1. Goes to DL Subscriber table
70 // 2. LportDispatcher From Scf. Matches on elanPseudoPort + SI=3. Goes to ELAN DMAC
71 // 3. ExtTunnelTable From L2GwDevice. Matches on VNI + SI=1. Sets ElanPseudoPort tag and goes
72 // to LportDispatcher table.
73 // And these rules must be programmed in all the Elan footprint
75 // Find the ElanInstance
76 Optional<ElanInstance> elanInstance = ElanServiceChainUtils.getElanInstanceByName(broker, elanName);
77 if ( !elanInstance.isPresent() ) {
78 LOG.debug("Could not find an Elan Instance with name={}", elanName);
82 Collection<BigInteger> elanDpnsOpc = ElanServiceChainUtils.getElanDpnsByName(broker, elanName);
83 if (elanDpnsOpc.isEmpty()) {
84 LOG.debug("Could not find any DPN related to Elan {}", elanName);
88 // updates map which stores relationship between elan and elanLPortTag and scfTag
89 ElanServiceChainUtils.updateElanToLportTagMap(broker, elanName, elanLportTag, scfTag, addOrRemove);
91 Long vni = elanInstance.get().getSegmentationId();
93 LOG.warn("There is no VNI for elan {}. VNI is mandatory. Returning", elanName);
97 int elanTag = elanInstance.get().getElanTag().intValue();
98 LOG.debug("elanName={} -> vni={} elanTag={}", elanName, vni, elanTag);
99 // For each DPN in the Elan, do
100 // Program LPortDispatcher to Scf
101 // Program LPortDispatcher from Scf
102 // Program ExtTunnelTable.
103 for (BigInteger dpnId : elanDpnsOpc) {
104 ElanServiceChainUtils.programLPortDispatcherToScf(mdsalManager, dpnId, elanTag, elanLportTag, tableId,
105 scfTag, addOrRemove);
106 ElanServiceChainUtils.programLPortDispatcherFromScf(mdsalManager, dpnId, elanLportTag, elanTag,
108 ElanServiceChainUtils.programExternalTunnelTable(mdsalManager, dpnId, elanLportTag, vni, elanTag,
114 public void removeElanPseudoPortFlows(String elanName, int elanLportTag) {
115 Optional<ElanServiceChainState> elanServiceChainState =
116 ElanServiceChainUtils.getElanServiceChainState(broker, elanName);
117 if (!elanServiceChainState.isPresent()) {
118 LOG.warn("Could not find ServiceChain state data for Elan {}, elanPseudoLportTag={}",
119 elanName, elanLportTag);
122 Optional<ElanInstance> elanInstance = ElanServiceChainUtils.getElanInstanceByName(broker, elanName);
123 if ( !elanInstance.isPresent() ) {
124 LOG.warn("Could not find ElanInstance for name {}", elanName);
128 Long vni = elanInstance.get().getSegmentationId();
130 LOG.warn("Elan {} is not related to a VNI. VNI is mandatory for ServiceChaining. Returning", elanName);
134 List<ElanToPseudoPortData> elanToPseudoPortDataList = elanServiceChainState.get().getElanToPseudoPortData();
135 if ( elanToPseudoPortDataList == null || elanToPseudoPortDataList.isEmpty() ) {
136 LOG.info("Could not find elan {} with elanPseudoPort {} participating in any ServiceChain",
137 elanName, elanLportTag);
141 if ( elanInstance.get().getElanTag() == null ) {
142 LOG.info("Could not find elanTag for elan {} ", elanName);
146 int elanTag = elanInstance.get().getElanTag().intValue();
148 List<BigInteger> operativeDPNs = NWUtil.getOperativeDPNs(broker);
149 for (ElanToPseudoPortData elanToPseudoPortData : elanToPseudoPortDataList) {
150 Long scfTag = elanToPseudoPortData.getScfTag();
152 for (BigInteger dpnId : operativeDPNs) {
153 ElanServiceChainUtils.programLPortDispatcherToScf(mdsalManager, dpnId, elanTag, elanLportTag,
154 CloudServiceChainConstants.SCF_DOWN_SUB_FILTER_TCP_BASED_TABLE,
155 scfTag, NwConstants.DEL_FLOW);
156 ElanServiceChainUtils.programLPortDispatcherFromScf(mdsalManager, dpnId, elanLportTag, elanTag,
157 NwConstants.DEL_FLOW);
158 ElanServiceChainUtils.programExternalTunnelTable(mdsalManager, dpnId, elanLportTag, vni, elanTag,
159 NwConstants.DEL_FLOW);
163 // Lastly, remove the serviceChain-state for the Elan
164 InstanceIdentifier<ElanServiceChainState> path =
165 InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanName))
166 .augmentation(ElanServiceChainState.class)
169 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, path);