bd8cc9790618ad56537735b416f6ff5f19a273fd
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / netvirt / openstack / netvirt / VLANProvider.java
1 /*
2  * Copyright (c) 2016 NEC Corporation 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
9 package org.opendaylight.netvirt.openstack.netvirt;
10
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15 import java.util.concurrent.ConcurrentHashMap;
16
17 import org.apache.commons.lang3.tuple.ImmutablePair;
18 import org.opendaylight.netvirt.openstack.netvirt.api.ConfigurationService;
19 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
20 import org.opendaylight.netvirt.openstack.netvirt.api.NodeCacheManager;
21 import org.opendaylight.netvirt.openstack.netvirt.api.VlanResponderProvider;
22 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
23 import org.opendaylight.netvirt.openstack.netvirt.impl.NeutronL3Adapter;
24 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
25 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
26 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
27 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronNetworkCRUD;
28 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronPortCRUD;
29 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
33 import org.osgi.framework.ServiceReference;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import com.google.common.base.Preconditions;
38
39 /**
40  * This class is used to add the flows when l3 is disabled in the ODL.
41  */
42 public class VLANProvider implements ConfigInterface {
43     private final Logger LOG = LoggerFactory.getLogger(VLANProvider.class);
44
45     // The implementation for each of these services is resolved by the OSGi Service Manager
46     private volatile ConfigurationService configurationService;
47     private volatile NodeCacheManager nodeCacheManager;
48     private volatile VlanResponderProvider vlanResponderProvider;
49     private volatile INeutronNetworkCRUD neutronNetworkCache;
50     private volatile INeutronPortCRUD neutronPortCache;
51     private Southbound southbound;
52     private volatile NeutronL3Adapter neutronL3Adapter;
53     private Map<String, Set<String>> vlanProviderCache = new ConcurrentHashMap<>();
54     private volatile boolean isCachePopulationDone = false;
55
56     public void programProviderNetworkFlow(Node envNode, OvsdbTerminationPointAugmentation port, NeutronNetwork network,
57             NeutronPort neutronPort, Boolean write) {
58         try {
59             final String brExt = configurationService.getExternalBridgeName();
60             final String portNameInt = getPatchPortName(brExt);
61             final String portNameExt = Constants.PATCH_PORT_TO_INTEGRATION_BRIDGE_NAME;
62             Long ofPort = port.getOfport();
63             String macAddress = neutronPort.getMacAddress();
64             final Long dpIdInt = getDpidForIntegrationBridge(envNode, portNameInt);
65             final Long dpIdExt = getDpidForExternalBridge();
66             Long patchIntPort = getPatchPort(dpIdInt, portNameInt);
67             Long patchExtPort = getPatchPort(dpIdExt, portNameExt);
68             Preconditions.checkNotNull(dpIdInt);
69             Preconditions.checkNotNull(dpIdExt);
70             Preconditions.checkNotNull(portNameInt);
71             vlanResponderProvider.programProviderNetworkRulesInternal(dpIdInt, network.getProviderSegmentationID(), ofPort,
72                     patchIntPort, macAddress, vlanProviderCache, write);
73
74             vlanResponderProvider.programProviderNetworkRulesExternal(dpIdExt, network.getProviderSegmentationID(),
75                     patchExtPort, macAddress, vlanProviderCache, write);
76         } catch(Exception e) {
77             LOG.error("programProviderNetworkFlow:Error while writing a flows. Caused due to, " + e.getMessage());
78         }
79     }
80
81     /**
82      * Construct patch port name based on external bridge name
83      *
84      * @param brExt String representing an External bridge.
85      * @return the string portNameExt.
86      */
87     public static String getPatchPortName(String brExt) {
88         String portNameExt = null;
89         if (brExt.contains("-")) {
90             String[] brExt_Ex = brExt.split("-");
91             portNameExt = Constants.MULTIPLE_NETWORK_L3_PATCH.concat("-").concat(brExt_Ex[1]);
92         } else {
93             portNameExt = Constants.MULTIPLE_NETWORK_L3_PATCH.concat("-").concat(brExt);
94         }
95         return portNameExt;
96     }
97
98     private Long getPatchPort(final Long dpId, final String portName) {
99         final Long dpidPrimitive = dpId;
100         for (Node node : nodeCacheManager.getBridgeNodes()) {
101             if (dpidPrimitive == southbound.getDataPathId(node)) {
102                 final OvsdbTerminationPointAugmentation terminationPointOfBridge =
103                         southbound.getTerminationPointOfBridge(node, portName);
104                 return (terminationPointOfBridge == null) ? null : terminationPointOfBridge.getOfport();
105             }
106         }
107         return null;
108     }
109
110     private void populateVLANProviderCaches() {
111         /*
112          * Rebuild the cache in case of a restart.
113          */
114         if (this.isCachePopulationDone || this.neutronPortCache == null
115                 || this.neutronNetworkCache == null) {
116             return;
117         }
118         this.isCachePopulationDone = true;
119         Set<String> lstMacAddress;
120         List<NeutronPort> neutronPorts = neutronPortCache.getAllPorts();
121         for (NeutronPort neutronPort : neutronPorts) {
122             if (neutronPort != null && neutronPort.getDeviceOwner().equalsIgnoreCase(Constants.OWNER_ROUTER_GATEWAY)) {
123                 final String macAddress = neutronPort.getMacAddress();
124                 final String networkUUID = neutronPort.getNetworkUUID();
125                 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
126                 if (neutronNetwork == null) {
127                     neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(networkUUID);
128                 }
129                 final String providerSegmentationId = neutronNetwork != null ?
130                                               neutronNetwork.getProviderSegmentationID() : null;
131                 LOG.debug("In populateVLANProviderCaches macAddress:" + macAddress +
132                         "providerSegmentationId:" + providerSegmentationId);
133                 if (providerSegmentationId == null || providerSegmentationId.isEmpty()
134                         || macAddress == null || macAddress.isEmpty()) {
135                     return;
136                 }
137                 if (vlanProviderCache != null && !vlanProviderCache.isEmpty() &&
138                         vlanProviderCache.containsKey(providerSegmentationId)) {
139                     lstMacAddress = vlanProviderCache.get(providerSegmentationId);
140                 } else {
141                     lstMacAddress = new HashSet<>();
142                     vlanProviderCache.put(providerSegmentationId, lstMacAddress);
143                 }
144                 lstMacAddress.add(macAddress);
145             }
146         }
147     }
148
149     @Override
150     public void setDependencies(final ServiceReference serviceReference) {
151         vlanResponderProvider =
152                 (VlanResponderProvider) ServiceHelper.getGlobalInstance(VlanResponderProvider.class, this);
153         configurationService =
154                 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
155         southbound =
156                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
157         nodeCacheManager =
158                 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
159         neutronL3Adapter =
160                 (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
161     }
162
163     @Override
164     public void setDependencies(final Object impl) {
165         if (impl instanceof VlanResponderProvider) {
166             vlanResponderProvider = (VlanResponderProvider)impl;
167         } else if (impl instanceof INeutronNetworkCRUD) {
168             neutronNetworkCache = (INeutronNetworkCRUD)impl;
169         } else if (impl instanceof INeutronPortCRUD) {
170             neutronPortCache = (INeutronPortCRUD)impl;
171         }
172         populateVLANProviderCaches();
173     }
174
175     private Long getDpidForIntegrationBridge(Node node, final String portName) {
176         if (southbound.getBridgeName(node).equals(configurationService.getIntegrationBridgeName())) {
177             TerminationPoint tp = southbound.readTerminationPoint(node, null, portName);
178             if (tp != null) {
179                 final long dpid = southbound.getDataPathId(node);
180                 return dpid;
181             }
182         }
183         return null;
184     }
185
186     private Long getDpidForExternalBridge() {
187         List<Long> dpids =  nodeCacheManager.getBridgeDpids(configurationService.getExternalBridgeName());
188         return dpids.get(0);
189     }
190 }