2355c733a8da5fd14bf56fce389a6825573ad3e0
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / servicebindings / flowbased / config / helpers / FlowBasedIngressServicesConfigUnbindHelper.java
1 /*
2  * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.genius.interfacemanager.servicebindings.flowbased.config.helpers;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.concurrent.ConcurrentHashMap;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.apache.aries.blueprint.annotation.service.Reference;
19 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
20 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
21 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
22 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
23 import org.opendaylight.genius.mdsalutil.MatchInfo;
24 import org.opendaylight.genius.mdsalutil.NwConstants;
25 import org.opendaylight.mdsal.binding.api.DataBroker;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.bound.services.state.list.BoundServicesState;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
31 import org.opendaylight.yangtools.yang.common.Uint64;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 @Singleton
36 public class FlowBasedIngressServicesConfigUnbindHelper extends AbstractFlowBasedServicesConfigUnbindHelper {
37
38     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedIngressServicesConfigUnbindHelper.class);
39
40     private final ManagedNewTransactionRunner txRunner;
41     private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
42
43     @Inject
44     public FlowBasedIngressServicesConfigUnbindHelper(@Reference final DataBroker dataBroker,
45             final InterfaceManagerCommonUtils interfaceManagerCommonUtils) {
46         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
47         this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
48     }
49
50     @Override
51     protected void unbindServiceOnInterface(List<ListenableFuture<Void>> futures, BoundServices boundServiceOld,
52                                             List<BoundServices> boundServices, BoundServicesState boundServicesState) {
53         // Split based on type of interface....
54         if (L2vlan.class.equals(boundServicesState.getInterfaceType())) {
55             unbindServiceOnVlan(futures, boundServiceOld, boundServices, boundServicesState);
56         } else if (Tunnel.class.equals(boundServicesState.getInterfaceType())) {
57             unbindServiceOnTunnel(futures, boundServiceOld, boundServices, boundServicesState);
58         }
59     }
60
61     private void unbindServiceOnVlan(List<ListenableFuture<Void>> futures, BoundServices boundServiceOld,
62                                             List<BoundServices> boundServices, BoundServicesState boundServicesState) {
63         LOG.info("unbinding ingress service {} for vlan port: {}", boundServiceOld.getServiceName(),
64                 boundServicesState.getInterfaceName());
65         futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
66             Uint64 dpId = boundServicesState.getDpid();
67             if (boundServices == null || boundServices.isEmpty()) {
68                 // Remove default entry from Lport Dispatcher Table.
69                 FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, boundServicesState.getInterfaceName(),
70                         boundServiceOld, tx, NwConstants.DEFAULT_SERVICE_INDEX);
71                 return;
72             }
73             BoundServices[] highLow =
74                     FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, boundServiceOld);
75             BoundServices low = highLow[0];
76             BoundServices high = highLow[1];
77             // This means the one removed was the highest priority service
78             if (high == null) {
79                 LOG.trace("Deleting ingress dispatcher table entry for service {}, match service index {}",
80                         boundServiceOld, NwConstants.DEFAULT_SERVICE_INDEX);
81                 FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, boundServicesState.getInterfaceName(),
82                         boundServiceOld, tx, NwConstants.DEFAULT_SERVICE_INDEX);
83                 if (low != null) {
84                     // delete the lower services flow entry.
85                     LOG.trace("Deleting ingress dispatcher table entry for lower service {}, match service index {}",
86                             low, low.getServicePriority().toJava());
87                     FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, boundServicesState.getInterfaceName(), low,
88                             tx, low.getServicePriority().toJava());
89                     BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, low)[0];
90                     short lowerServiceIndex = (short) (lower != null ? lower.getServicePriority().toJava()
91                             : low.getServicePriority().toJava() + 1);
92                     LOG.trace("Installing new ingress dispatcher table entry for lower service {}, match service index "
93                                     + "{}, update service index {}",
94                             low, NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
95                     FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, low, boundServicesState.getInterfaceName(),
96                             tx, boundServicesState.getIfIndex(), NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
97                 }
98             } else {
99                 LOG.trace("Deleting ingress dispatcher table entry for service {}, match service index {}",
100                         boundServiceOld, boundServiceOld.getServicePriority());
101                 FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, boundServicesState.getInterfaceName(),
102                         boundServiceOld, tx, boundServiceOld.getServicePriority().toJava());
103                 short lowerServiceIndex = (short) (low != null ? low.getServicePriority().toJava()
104                         : boundServiceOld.getServicePriority().toJava() + 1);
105                 BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(boundServices);
106                 if (high.equals(highest)) {
107                     LOG.trace("Update the existing higher service {}, match service index {}, update service index {}",
108                             high, NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
109                     FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, boundServicesState.getInterfaceName(),
110                             tx, boundServicesState.getIfIndex(), NwConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
111                 } else {
112                     LOG.trace("Update the existing higher service {}, match service index {}, update service index {}",
113                             high, high.getServicePriority(), lowerServiceIndex);
114                     FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, boundServicesState.getInterfaceName(),
115                             tx, boundServicesState.getIfIndex(), high.getServicePriority().toJava(), lowerServiceIndex);
116                 }
117             }
118         }));
119     }
120
121     private void unbindServiceOnTunnel(List<ListenableFuture<Void>> futures, BoundServices boundServiceOld,
122                                        List<BoundServices> boundServices, BoundServicesState boundServicesState) {
123         futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
124             Uint64 dpId = boundServicesState.getDpid();
125
126             LOG.info("unbinding ingress service {} for tunnel port: {}", boundServiceOld.getServiceName(),
127                     boundServicesState.getInterfaceName());
128
129             if (boundServices.isEmpty()) {
130                 // Remove entry from Ingress Table.
131                 FlowBasedServicesUtils.removeIngressFlow(boundServicesState.getInterfaceName(), boundServiceOld, dpId,
132                         tx);
133                 return;
134             }
135
136             Map<Short, BoundServices> tmpServicesMap = new ConcurrentHashMap<>();
137             short highestPriority = 0xFF;
138             for (BoundServices boundService : boundServices) {
139                 tmpServicesMap.put(boundService.getServicePriority().toJava(), boundService);
140                 if (boundService.getServicePriority().toJava() < highestPriority) {
141                     highestPriority = boundService.getServicePriority().toJava();
142                 }
143             }
144
145             if (highestPriority < boundServiceOld.getServicePriority().toJava()) {
146                 FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, boundServicesState.getInterfaceName(),
147                         boundServiceOld, tx, boundServiceOld.getServicePriority().toJava());
148                 return;
149             }
150
151             List<MatchInfo> matches;
152             long portNo = boundServicesState.getPortNo().toJava();
153             matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable(dpId, portNo);
154
155             BoundServices toBeMoved = tmpServicesMap.get(highestPriority);
156             Interface iface =
157                     interfaceManagerCommonUtils.getInterfaceFromConfigDS(boundServicesState.getInterfaceName());
158             FlowBasedServicesUtils.removeIngressFlow(iface.getName(), boundServiceOld, dpId, tx);
159             FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, toBeMoved, tx, matches,
160                     boundServicesState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
161             FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), toBeMoved, tx,
162                     toBeMoved.getServicePriority().toJava());
163         }));
164     }
165
166     @Override
167     protected void unbindServiceOnInterfaceType(List<ListenableFuture<Void>> futures, BoundServices boundServiceNew,
168                                                 List<BoundServices> allServices) {
169         LOG.info("unbindServiceOnInterfaceType Ingress - WIP");
170     }
171 }