Merge "ITM: Fix for tunnel ports not getting deleted."
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / renderer / ovs / utilities / SouthboundUtils.java
1 /*
2  * Copyright (c) 2016 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.renderer.ovs.utilities;
9
10 import com.google.common.collect.Maps;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntry;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBfd;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlanGpe;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfd;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 public class SouthboundUtils {
63     private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
64
65     public static final String BFD_PARAM_ENABLE = "enable";
66     static final String BFD_PARAM_MIN_TX = "min_tx";
67     static final String BFD_PARAM_MIN_RX = "min_rx";
68     static final String BFD_PARAM_DECAY_MIN_RX = "decay_min_rx";
69     static final String BFD_PARAM_FORWARDING_IF_RX = "forwarding_if_rx";
70     static final String BFD_PARAM_CPATH_DOWN = "cpath_down";
71     static final String BFD_PARAM_CHECK_TNL_KEY = "check_tnl_key";
72
73     // bfd params
74     public static final String BFD_OP_STATE = "state";
75     public static final String BFD_STATE_UP = "up";
76     private static final String BFD_MIN_RX_VAL = "1000";
77     private static final String BFD_MIN_TX_VAL = "100";
78     private static final String BFD_DECAY_MIN_RX_VAL = "200";
79     private static final String BFD_FORWARDING_IF_RX_VAL = "true";
80     private static final String BFD_CPATH_DOWN_VAL = "false";
81     private static final String BFD_CHECK_TNL_KEY_VAL = "false";
82
83     // Tunnel options
84     private static final String TUNNEL_OPTIONS_KEY = "key";
85     private static final String TUNNEL_OPTIONS_LOCAL_IP = "local_ip";
86     private static final String TUNNEL_OPTIONS_REMOTE_IP = "remote_ip";
87
88     // Options for VxLAN-GPE + NSH tunnels
89     private static final String TUNNEL_OPTIONS_EXTS = "exts";
90     private static final String TUNNEL_OPTIONS_NSI = "nsi";
91     private static final String TUNNEL_OPTIONS_NSP = "nsp";
92     private static final String TUNNEL_OPTIONS_NSHC1 = "nshc1";
93     private static final String TUNNEL_OPTIONS_NSHC2 = "nshc2";
94     private static final String TUNNEL_OPTIONS_NSHC3 = "nshc3";
95     private static final String TUNNEL_OPTIONS_NSHC4 = "nshc4";
96
97     // Values for VxLAN-GPE + NSH tunnels
98     private static final String TUNNEL_OPTIONS_VALUE_FLOW = "flow";
99     private static final String TUNNEL_OPTIONS_VALUE_GPE = "gpe";
100
101     public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
102
103     // To keep the mapping between Tunnel Types and Tunnel Interfaces
104     private static final Map<Class<? extends TunnelTypeBase>, Class<? extends InterfaceTypeBase>> TUNNEL_TYPE_MAP = new HashMap<Class<? extends TunnelTypeBase>, Class<? extends InterfaceTypeBase>>() {
105         {
106             put(TunnelTypeGre.class, InterfaceTypeGre.class);
107             put(TunnelTypeVxlan.class, InterfaceTypeVxlan.class);
108             put(TunnelTypeVxlanGpe.class, InterfaceTypeVxlan.class);
109         }
110     };
111
112     public static void addPortToBridge(InstanceIdentifier<?> bridgeIid, Interface iface,
113             OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName, String portName, DataBroker dataBroker,
114             List<ListenableFuture<Void>> futures) {
115         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
116         IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
117         if (ifTunnel != null) {
118             addTunnelPortToBridge(ifTunnel, bridgeIid, iface, bridgeAugmentation, bridgeName, portName, dataBroker, tx);
119         }
120         futures.add(tx.submit());
121     }
122
123     /*
124      * add all tunnels ports corresponding to the bridge to the topology config
125      * DS
126      */
127     public static void addAllPortsToBridge(BridgeEntry bridgeEntry, DataBroker dataBroker,
128             InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid, OvsdbBridgeAugmentation bridgeNew,
129             List<ListenableFuture<Void>> futures) {
130         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
131         String bridgeName = bridgeNew.getBridgeName().getValue();
132         LOG.debug("adding all ports to bridge: {}", bridgeName);
133         List<BridgeInterfaceEntry> bridgeInterfaceEntries = bridgeEntry.getBridgeInterfaceEntry();
134         if (bridgeInterfaceEntries != null) {
135             for (BridgeInterfaceEntry bridgeInterfaceEntry : bridgeInterfaceEntries) {
136                 String portName = bridgeInterfaceEntry.getInterfaceName();
137                 InterfaceKey interfaceKey = new InterfaceKey(portName);
138                 Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
139                 if (iface != null) {
140                     IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
141                     if (ifTunnel != null) {
142                         addTunnelPortToBridge(ifTunnel, bridgeIid, iface, bridgeNew, bridgeName, portName, dataBroker,
143                                 writeTransaction);
144                     }
145                 } else {
146                     LOG.debug("Interface {} not found in config DS", portName);
147                 }
148             }
149         }
150         futures.add(writeTransaction.submit());
151     }
152
153     /*
154      * add all tunnels ports corresponding to the bridge to the topology config
155      * DS
156      */
157     public static void removeAllPortsFromBridge(BridgeEntry bridgeEntry, DataBroker dataBroker,
158             InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid, OvsdbBridgeAugmentation bridgeNew,
159             List<ListenableFuture<Void>> futures) {
160         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
161         String bridgeName = bridgeNew.getBridgeName().getValue();
162         LOG.debug("removing all ports from bridge: {}", bridgeName);
163         List<BridgeInterfaceEntry> bridgeInterfaceEntries = bridgeEntry.getBridgeInterfaceEntry();
164         if (bridgeInterfaceEntries != null) {
165             for (BridgeInterfaceEntry bridgeInterfaceEntry : bridgeInterfaceEntries) {
166                 String portName = bridgeInterfaceEntry.getInterfaceName();
167                 InterfaceKey interfaceKey = new InterfaceKey(portName);
168                 Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
169                 if (iface != null) {
170                     IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
171                     if (ifTunnel != null) {
172                         removeTerminationEndPoint(futures, dataBroker, bridgeIid, iface.getName());
173                     }
174                 } else {
175                     LOG.debug("Interface {} not found in config DS", portName);
176                 }
177             }
178         }
179         futures.add(writeTransaction.submit());
180     }
181
182     private static void addVlanPortToBridge(InstanceIdentifier<?> bridgeIid, IfL2vlan ifL2vlan, IfTunnel ifTunnel,
183             OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName, String portName, DataBroker dataBroker,
184             WriteTransaction t) {
185         if (ifL2vlan.getVlanId() != null) {
186             addTerminationPoint(bridgeIid, bridgeAugmentation, bridgeName, portName, ifL2vlan.getVlanId().getValue(),
187                     null, null, ifTunnel, t);
188         }
189     }
190
191     private static void addTunnelPortToBridge(IfTunnel ifTunnel, InstanceIdentifier<?> bridgeIid, Interface iface,
192             OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName, String portName, DataBroker dataBroker,
193             WriteTransaction t) {
194         LOG.debug("adding tunnel port {} to bridge {}", portName, bridgeName);
195
196         Class<? extends InterfaceTypeBase> type = TUNNEL_TYPE_MAP.get(ifTunnel.getTunnelInterfaceType());
197
198         if (type == null) {
199             LOG.warn("Unknown Tunnel Type obtained while creating interface: {}", iface);
200             return;
201         }
202
203         int vlanId = 0;
204         IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
205         if (ifL2vlan != null && ifL2vlan.getVlanId() != null) {
206             vlanId = ifL2vlan.getVlanId().getValue();
207         }
208
209         Map<String, String> options = Maps.newHashMap();
210
211         // Options common to any kind of tunnel
212         IpAddress localIp = ifTunnel.getTunnelSource();
213         options.put(TUNNEL_OPTIONS_LOCAL_IP, localIp.getIpv4Address().getValue());
214
215         IpAddress remoteIp = ifTunnel.getTunnelDestination();
216         options.put(TUNNEL_OPTIONS_REMOTE_IP, remoteIp.getIpv4Address().getValue());
217
218         // Specific options for each type of tunnel
219         if (!ifTunnel.getTunnelInterfaceType().equals(TunnelTypeMplsOverGre.class)) {
220             options.put(TUNNEL_OPTIONS_KEY, TUNNEL_OPTIONS_VALUE_FLOW);
221         }
222         if (ifTunnel.getTunnelInterfaceType().equals(TunnelTypeVxlanGpe.class)) {
223             options.put(TUNNEL_OPTIONS_EXTS, TUNNEL_OPTIONS_VALUE_GPE);
224             options.put(TUNNEL_OPTIONS_NSI, TUNNEL_OPTIONS_VALUE_FLOW);
225             options.put(TUNNEL_OPTIONS_NSP, TUNNEL_OPTIONS_VALUE_FLOW);
226             options.put(TUNNEL_OPTIONS_NSHC1, TUNNEL_OPTIONS_VALUE_FLOW);
227             options.put(TUNNEL_OPTIONS_NSHC2, TUNNEL_OPTIONS_VALUE_FLOW);
228             options.put(TUNNEL_OPTIONS_NSHC3, TUNNEL_OPTIONS_VALUE_FLOW);
229             options.put(TUNNEL_OPTIONS_NSHC4, TUNNEL_OPTIONS_VALUE_FLOW);
230         }
231         addTerminationPoint(bridgeIid, bridgeAugmentation, bridgeName, portName, vlanId, type, options, ifTunnel, t);
232     }
233
234     // Update is allowed only for tunnel monitoring attributes
235     public static void updateBfdParamtersForTerminationPoint(InstanceIdentifier<?> bridgeIid, IfTunnel ifTunnel,
236             String portName, WriteTransaction transaction) {
237         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
238                 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), portName);
239         LOG.debug("update bfd parameters for interface {}", tpIid);
240         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
241         List<InterfaceBfd> bfdParams = getBfdParams(ifTunnel);
242         tpAugmentationBuilder.setInterfaceBfd(bfdParams);
243
244         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
245         tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
246         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
247
248         transaction.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build(), true);
249     }
250
251     private static void addTerminationPoint(InstanceIdentifier<?> bridgeIid, OvsdbBridgeAugmentation bridgeNode,
252             String bridgeName, String portName, int vlanId, Class<? extends InterfaceTypeBase> type,
253             Map<String, String> options, IfTunnel ifTunnel, WriteTransaction t) {
254         InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
255                 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), portName);
256         OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
257
258         tpAugmentationBuilder.setName(portName);
259
260         if (type != null) {
261             tpAugmentationBuilder.setInterfaceType(type);
262         }
263
264         if (options != null) {
265             List<Options> optionsList = new ArrayList<>();
266             for (Map.Entry<String, String> entry : options.entrySet()) {
267                 OptionsBuilder optionsBuilder = new OptionsBuilder();
268                 optionsBuilder.setKey(new OptionsKey(entry.getKey()));
269                 optionsBuilder.setOption(entry.getKey());
270                 optionsBuilder.setValue(entry.getValue());
271                 optionsList.add(optionsBuilder.build());
272             }
273             tpAugmentationBuilder.setOptions(optionsList);
274         }
275
276         if (vlanId != 0) {
277             tpAugmentationBuilder.setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Access);
278             tpAugmentationBuilder.setVlanTag(new VlanId(vlanId));
279         }
280
281         if (bfdMonitoringEnabled(ifTunnel)) {
282             List<InterfaceBfd> bfdParams = getBfdParams(ifTunnel);
283             tpAugmentationBuilder.setInterfaceBfd(bfdParams);
284         }
285
286         TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
287         tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
288         tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
289
290         t.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build(), true);
291
292     }
293
294     private static List<InterfaceBfd> getBfdParams(IfTunnel ifTunnel) {
295         List<InterfaceBfd> bfdParams = new ArrayList<>();
296         bfdParams.add(getIfBfdObj(BFD_PARAM_ENABLE,ifTunnel != null ? ifTunnel.isMonitorEnabled().toString() :"false"));
297         bfdParams.add(getIfBfdObj(BFD_PARAM_MIN_TX, ifTunnel != null &&  ifTunnel.getMonitorInterval() != null ?
298                 ifTunnel.getMonitorInterval().toString() : BFD_MIN_TX_VAL));
299         return bfdParams;
300     }
301
302     private static InterfaceBfd getIfBfdObj(String key, String value) {
303         InterfaceBfdBuilder bfdBuilder = new InterfaceBfdBuilder();
304         bfdBuilder.setBfdKey(key).setKey(new InterfaceBfdKey(key)).setBfdValue(value);
305         return bfdBuilder.build();
306     }
307
308     public static InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(NodeKey nodekey,
309             String portName) {
310         InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier.create(NetworkTopology.class)
311                 .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID)).child(Node.class, nodekey)
312                 .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
313
314         LOG.debug("Termination point InstanceIdentifier generated : {}", terminationPointPath);
315         return terminationPointPath;
316     }
317
318     public static void removeTerminationEndPoint(List<ListenableFuture<Void>> futures, DataBroker dataBroker,
319             InstanceIdentifier<?> bridgeIid, String interfaceName) {
320         LOG.debug("removing termination point for {}", interfaceName);
321         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
322         InstanceIdentifier<TerminationPoint> tpIid = SouthboundUtils.createTerminationPointInstanceIdentifier(
323                 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceName);
324         transaction.delete(LogicalDatastoreType.CONFIGURATION, tpIid);
325         futures.add(transaction.submit());
326     }
327
328     public static boolean bfdMonitoringEnabled(IfTunnel ifTunnel) {
329         if (ifTunnel.isMonitorEnabled()
330                 && TunnelMonitoringTypeBfd.class.isAssignableFrom(ifTunnel.getMonitorProtocol())) {
331             return true;
332         }
333         return false;
334     }
335
336     public static boolean isMonitorProtocolBfd(IfTunnel ifTunnel) {
337         if (TunnelMonitoringTypeBfd.class.isAssignableFrom(ifTunnel.getMonitorProtocol())) {
338             return true;
339         }
340         return false;
341
342     }
343 }