2 * Copyright (c) 2020 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.genius.itm.servicebinding;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
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;
53 public final class BindServiceUtils {
55 private static final Logger LOG = LoggerFactory.getLogger(BindServiceUtils.class);
57 private BindServiceUtils() {
58 throw new IllegalStateException("Utility class");
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);
69 public static void bindDefaultEgressDispatcherService(ManagedNewTransactionRunner txRunner,
70 List<ListenableFuture<Void>> futures,
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);
85 public static Map<InstructionKey, Instruction> getEgressInstructionsForInterface(String tunType,String portNo,
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);
98 public static List<ActionInfo> getEgressActionInfosForInterface(String tunType, String portNo,
100 int actionKeyStart, boolean isDefaultEgress,
101 Uint16 ifIndex, long groupId) {
102 List<ActionInfo> result = new ArrayList<>();
104 case "MPLS_OVER_GRE":
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) {
114 result.add(new ActionSetFieldTunnelId(actionKeyStart++, Uint64.valueOf(tunnelKey)));
115 addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
117 result.add(new ActionOutput(actionKeyStart++, new Uri(portNo)));
121 case "VXLAN_TRUNK_INTERFACE":
122 if (!isDefaultEgress) {
123 if (tunnelKey != null) {
124 result.add(new ActionSetFieldTunnelId(actionKeyStart++, Uint64.valueOf(tunnelKey)));
126 addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
128 result.add(new ActionOutput(actionKeyStart++, new Uri(portNo)));
131 case "VLAN_INTERFACE":
132 LOG.error("VLAN swicth case");
133 if (isDefaultEgress) {
134 result.add(new ActionOutput(actionKeyStart++, new Uri(portNo)));
136 addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
139 case "LOGICAL_GROUP_INTERFACE":
140 if (isDefaultEgress) {
141 result.add(new ActionGroup(groupId));
143 addEgressActionInfosForInterface(ifIndex, actionKeyStart, result);
148 LOG.warn("Interface Type {} not handled yet", tunType);
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));
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();
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);
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();
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))));
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);
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();