OF port deletion complete implementation
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / servicebinding / BindServiceUtils.java
1 /*
2  * Copyright (c) 2020 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.itm.servicebinding;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import org.opendaylight.genius.infra.Datastore;
18 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
19 import org.opendaylight.genius.infra.TypedWriteTransaction;
20 import org.opendaylight.genius.itm.globals.ITMConstants;
21 import org.opendaylight.genius.mdsalutil.ActionInfo;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
24 import org.opendaylight.genius.mdsalutil.NwConstants;
25 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
26 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
27 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
28 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
29 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
30 import org.opendaylight.genius.utils.ServiceIndex;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.common.Uint16;
48 import org.opendaylight.yangtools.yang.common.Uint64;
49 import org.opendaylight.yangtools.yang.common.Uint8;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 public final class BindServiceUtils {
54
55     private static final Logger LOG = LoggerFactory.getLogger(BindServiceUtils.class);
56
57     private BindServiceUtils() {
58         throw new IllegalStateException("Utility class");
59     }
60
61     public static void bindDefaultEgressDispatcherService(ManagedNewTransactionRunner txRunner,
62                                                           List<ListenableFuture<Void>> futures, String tunType,
63                                                           String portNo, String interfaceName, Uint16 ifIndex) {
64         Map<InstructionKey, Instruction> instructions =
65                 getEgressInstructionsForInterface(tunType, portNo, null, true, ifIndex, 0);
66         bindDefaultEgressDispatcherService(txRunner, futures, interfaceName, instructions);
67     }
68
69     public static void bindDefaultEgressDispatcherService(ManagedNewTransactionRunner txRunner,
70                                                           List<ListenableFuture<Void>> futures,
71                                                           String interfaceName,
72                                                           Map<InstructionKey, Instruction> instructions) {
73         futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
74             int priority = ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
75                     NwConstants.DEFAULT_EGRESS_SERVICE_INDEX);
76             BoundServices serviceInfo =
77                     getBoundServices(String.format("%s.%s", "default", interfaceName),
78                             ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
79                                     NwConstants.DEFAULT_EGRESS_SERVICE_INDEX),
80                             priority, NwConstants.EGRESS_DISPATCHER_TABLE_COOKIE, instructions);
81             bindService(tx, interfaceName, serviceInfo, ServiceModeEgress.class);
82         }));
83     }
84
85     public static Map<InstructionKey, Instruction> getEgressInstructionsForInterface(String tunType,String portNo,
86                                                                                      Long tunnelKey,
87                                                                                      boolean isDefaultEgress,
88                                                                                      Uint16 ifIndex, long groupId) {
89         Map<InstructionKey, Instruction> instructions = new HashMap<>();
90         List<Action> actionList = MDSALUtil.buildActions(
91                 getEgressActionInfosForInterface(tunType, portNo, tunnelKey, 0,
92                         isDefaultEgress, ifIndex, groupId));
93         Instruction inst = MDSALUtil.buildApplyActionsInstruction(actionList);
94         instructions.put(inst.key(), inst);
95         return instructions;
96     }
97
98     public static List<ActionInfo> getEgressActionInfosForInterface(String tunType, String portNo,
99                                                                     Long tunnelKey,
100                                                                     int actionKeyStart, boolean isDefaultEgress,
101                                                                     Uint16 ifIndex, long groupId) {
102         List<ActionInfo> result = new ArrayList<>();
103         switch (tunType) {
104             case "MPLS_OVER_GRE":
105                 // fall through
106             case "GRE_TRUNK_INTERFACE":
107                 if (!isDefaultEgress) {
108                     // TODO tunnel_id to encode GRE key, once it is supported
109                     // Until then, tunnel_id should be "cleaned", otherwise it
110                     // stores the value coming from a VXLAN tunnel
111                     if (tunnelKey == null) {
112                         tunnelKey = 0L;
113                     }
114                     result.add(new ActionSetFieldTunnelId(actionKeyStart++, Uint64.valueOf(tunnelKey)));
115                     addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
116                 } else {
117                     result.add(new ActionOutput(actionKeyStart++, new Uri(portNo)));
118                 }
119                 break;
120                 // fall through
121             case "VXLAN_TRUNK_INTERFACE":
122                 if (!isDefaultEgress) {
123                     if (tunnelKey != null) {
124                         result.add(new ActionSetFieldTunnelId(actionKeyStart++, Uint64.valueOf(tunnelKey)));
125                     }
126                     addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
127                 } else {
128                     result.add(new ActionOutput(actionKeyStart++, new Uri(portNo)));
129                 }
130                 break;
131             case "VLAN_INTERFACE":
132                 LOG.error("VLAN swicth case");
133                 if (isDefaultEgress) {
134                     result.add(new ActionOutput(actionKeyStart++, new Uri(portNo)));
135                 } else {
136                     addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
137                 }
138                 break;
139             case "LOGICAL_GROUP_INTERFACE":
140                 if (isDefaultEgress) {
141                     result.add(new ActionGroup(groupId));
142                 } else {
143                     addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
144                 }
145                 break;
146
147             default:
148                 LOG.warn("Interface Type {} not handled yet", tunType);
149                 break;
150         }
151         return result;
152     }
153
154     public static void addEgressActionInfosForInterface(Uint16 ifIndex, int actionKeyStart, List<ActionInfo> result) {
155         long regValue = MetaDataUtil.getReg6ValueForLPortDispatcher(ifIndex.intValue(),
156                 NwConstants.DEFAULT_SERVICE_INDEX);
157         result.add(new ActionRegLoad(actionKeyStart++, NxmNxReg6.class, ITMConstants.REG6_START_INDEX,
158                 ITMConstants.REG6_END_INDEX, regValue));
159         result.add(new ActionNxResubmit(actionKeyStart, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE));
160     }
161
162     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
163                                                  Uint64 cookie, Map<InstructionKey, Instruction> instructions) {
164         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie)
165                 .setFlowPriority(Uint16.valueOf(flowPriority))
166                 .setInstruction(instructions);
167         return new BoundServicesBuilder()
168                 .withKey(new BoundServicesKey(Uint8.valueOf(servicePriority)))
169                 .setServiceName(serviceName)
170                 .setServicePriority(Uint8.valueOf(servicePriority))
171                 .setServiceType(ServiceTypeFlowBased.class)
172                 .addAugmentation(augBuilder.build()).build();
173     }
174
175     public static void bindService(TypedWriteTransaction<Datastore.Configuration> tx, String interfaceName,
176                                    BoundServices serviceInfo,
177                                    Class<? extends ServiceModeBase> serviceMode) {
178         LOG.info("Binding Service {} for : {}", serviceInfo.getServiceName(), interfaceName);
179         InstanceIdentifier<BoundServices> boundServicesInstanceIdentifier = buildBoundServicesIId(
180                 serviceInfo.getServicePriority(), interfaceName, serviceMode);
181         tx.mergeParentStructurePut(boundServicesInstanceIdentifier, serviceInfo);
182     }
183
184     public static InstanceIdentifier<BoundServices> buildBoundServicesIId(Uint8 servicePriority, String interfaceName,
185                                                                       Class<? extends ServiceModeBase> serviceMode) {
186         return InstanceIdentifier.builder(ServiceBindings.class)
187                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
188                 .child(BoundServices.class, new BoundServicesKey(servicePriority)).build();
189     }
190
191     public static void unbindService(List<ListenableFuture<Void>> futures,
192                                      ManagedNewTransactionRunner txRunner,
193                                      String interfaceName) {
194         LOG.info("Unbinding service for : {}", interfaceName);
195         futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
196             tx -> tx.delete(buildDefaultServiceId(interfaceName))));
197     }
198
199     public static InstanceIdentifier<BoundServices> buildDefaultServiceId(String interfaceName) {
200         return buildServiceId(interfaceName, ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME,
201                 NwConstants.DEFAULT_EGRESS_SERVICE_INDEX), ServiceModeEgress.class);
202     }
203
204     public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
205                                                                    Class<? extends ServiceModeBase> serviceMode) {
206         return InstanceIdentifier.builder(ServiceBindings.class)
207                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
208                 .child(BoundServices.class, new BoundServicesKey(Uint8.valueOf(serviceIndex))).build();
209     }
210 }