2 * Copyright (c) 2016 NEC Corporation 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
9 package org.opendaylight.ovsdb.openstack.netvirt.impl;
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.List;
15 import com.google.common.base.Preconditions;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
20 import org.opendaylight.ovsdb.openstack.netvirt.api.Status;
21 import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode;
22 import org.opendaylight.ovsdb.openstack.netvirt.ConfigInterface;
23 import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
24 import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
25 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronNetwork;
26 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronPort;
27 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronNetworkCRUD;
28 import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronPortCRUD;
29 import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
30 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
31 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
34 import org.osgi.framework.ServiceReference;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * ARP flows programmed for Neutron port.
41 public class DistributedArpService implements ConfigInterface {
43 private static final Logger LOG = LoggerFactory.getLogger(DistributedArpService.class);
44 // The implementation for each of these services is resolved by the OSGi Service Manager
45 private volatile ConfigurationService configurationService;
46 private volatile TenantNetworkManager tenantNetworkManager;
47 private volatile NodeCacheManager nodeCacheManager;
48 private volatile INeutronNetworkCRUD neutronNetworkCache;
49 private volatile INeutronPortCRUD neutronPortCache;
50 private volatile ArpProvider arpProvider;
51 private volatile NeutronL3Adapter neutronL3Adapter;
53 private Southbound southbound;
54 private Boolean flgDistributedARPEnabled = true;
56 private void initMembers() {
57 Preconditions.checkNotNull(configurationService);
58 if (configurationService.isDistributedArpDisabled()) {
59 this.flgDistributedARPEnabled = false;
60 LOG.debug("Distributed ARP responder is disabled");
62 LOG.debug("Distributed ARP responder is enabled");
67 * Process the port event to write Arp rules for neutron ports.
69 * @param action the {@link org.opendaylight.ovsdb.openstack.netvirt.api.Action} action to be handled.
70 * @param neutronPort An instance of NeutronPort object.
72 public void handlePortEvent(NeutronPort neutronPort, Action action) {
73 LOG.debug("neutronPort Event {} action event {} ", neutronPort, action);
74 if (action == Action.DELETE) {
75 this.handleNeutornPortForArp(neutronPort, action);
77 for (NeutronPort neutronPort1 : neutronPortCache.getAllPorts()) {
78 this.handleNeutornPortForArp(neutronPort1, action);
84 * Arp rules are added/removed based on neutron port event
87 boolean programStaticRuleStage1(Long dpid, String segOrOfPort,
88 String macAddress, String ipStr,
90 if (action == Action.DELETE ) {
91 LOG.trace("Deleting Flow : programStaticArpStage1 dpid {} segOrOfPort {} mac {} ip {} action {}",
92 dpid, segOrOfPort, macAddress, ipStr, action);
94 if (action == Action.ADD) {
95 LOG.trace("Adding Flow : programStaticArpStage1 dpid {} segOrOfPort {} mac {} ip {} action {}",
96 dpid, segOrOfPort, macAddress, ipStr, action);
99 Status status = this.programStaticRuleStage2(dpid, segOrOfPort, macAddress, ipStr, action);
100 return status.isSuccess();
104 * Arp rules are programmed by invoke arpProvider
107 private Status programStaticRuleStage2(Long dpid,
114 InetAddress inetAddress = InetAddress.getByName(address);
115 status = arpProvider == null ?
116 new Status(StatusCode.SUCCESS) :
117 arpProvider.programStaticArpEntry(dpid, segOrOfPort,
118 macAddress, inetAddress, action);
119 } catch (UnknownHostException e) {
120 status = new Status(StatusCode.BADREQUEST);
123 if (status.isSuccess()) {
124 LOG.debug("programStaticRuleStage2 {} for mac:{} addr:{} dpid:{} segOrOfPort:{} action:{}",
125 arpProvider == null ? "skipped" : "programmed",
126 macAddress, address, dpid, segOrOfPort, action);
128 LOG.error("programStaticRuleStage2 failed for mac:{} addr:{} dpid:{} segOrOfPort:{} action:{} status:{}",
129 macAddress, address, dpid, segOrOfPort, action, status);
135 * Write Arp rules based on event for neutron port.
137 * @param action the {@link org.opendaylight.ovsdb.openstack.netvirt.api.Action} action to be handled.
138 * @param neutronPort An instance of NeutronPort object.
140 private void handleNeutornPortForArp(NeutronPort neutronPort, Action action) {
142 final String networkUUID = neutronPort.getNetworkUUID();
143 NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
144 if (null == neutronNetwork) {
145 neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(networkUUID);
147 final String providerSegmentationId = neutronNetwork != null ?
148 neutronNetwork.getProviderSegmentationID() : null;
149 final String tenantMac = neutronPort.getMacAddress();
150 if (providerSegmentationId == null || providerSegmentationId.isEmpty() ||
151 tenantMac == null || tenantMac.isEmpty()) {
152 // done: go no further w/out all the info needed...
156 final boolean isDelete = action == Action.DELETE;
157 final Action action1 = isDelete ? Action.DELETE : Action.ADD;
160 List<Node> nodes = nodeCacheManager.getBridgeNodes();
161 if (nodes.isEmpty()) {
162 LOG.trace("updateL3ForNeutronPort has no nodes to work with");
164 for (Node node : nodes) {
165 final Long dpid = getDatapathIdIntegrationBridge(node);
169 if (neutronPort.getFixedIPs() == null) {
172 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
173 final String tenantIpStr = neutronIP.getIpAddress();
174 if (tenantIpStr.isEmpty()) {
177 // Configure distributed ARP responder
178 if (flgDistributedARPEnabled) {
179 // Arp rule is only needed when segmentation exists in the given node (bug 4752).
180 boolean arpNeeded = tenantNetworkManager.isTenantNetworkPresentInNode(node, providerSegmentationId);
181 final Action actionForNode = arpNeeded ? action1 : Action.DELETE;
182 programStaticRuleStage1(dpid, providerSegmentationId, tenantMac, tenantIpStr, actionForNode);
189 * Check if node is integration bridge, then return its datapathID.
190 * @param bridgeNode An instance of Node object.
192 private Long getDatapathIdIntegrationBridge(Node node) {
193 if (southbound.getBridge(node, configurationService.getIntegrationBridgeName()) != null) {
194 return southbound.getDataPathId(node);
202 * @param bridgeNode An instance of Node object.
203 * @param intf An {@link org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105
204 * .OvsdbTerminationPointAugmentation} instance of OvsdbTerminationPointAugmentation object.
205 * @param neutronNetwork An {@link org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronNetwork} instance of NeutronNetwork
207 * @param action the {@link org.opendaylight.ovsdb.openstack.netvirt.api.Action} action to be handled.
209 public void processInterfaceEvent(final Node bridgeNode, final OvsdbTerminationPointAugmentation intf,
210 final NeutronNetwork neutronNetwork, Action action) {
211 LOG.debug("southbound interface {} node:{} interface:{}, neutronNetwork:{}",
212 action, bridgeNode.getNodeId().getValue(), intf.getName(), neutronNetwork);
213 final NeutronPort neutronPort = tenantNetworkManager.getTenantPort(intf);
214 if (neutronPort != null) {
215 this.handlePortEvent(neutronPort, action);
220 public void setDependencies(ServiceReference serviceReference) {
221 tenantNetworkManager =
222 (TenantNetworkManager) ServiceHelper.getGlobalInstance(TenantNetworkManager.class, this);
223 configurationService =
224 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
226 (ArpProvider) ServiceHelper.getGlobalInstance(ArpProvider.class, this);
228 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
230 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
232 (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
237 public void setDependencies(Object impl) {
238 if (impl instanceof INeutronNetworkCRUD) {
239 neutronNetworkCache = (INeutronNetworkCRUD)impl;
240 } else if (impl instanceof INeutronPortCRUD) {
241 neutronPortCache = (INeutronPortCRUD)impl;
242 } else if (impl instanceof ArpProvider) {
243 arpProvider = (ArpProvider)impl;