With this change the GatewayMacResolverService will become resilient to the cases
where nodes get deleted or lose br-ex connectivity after the resolver is kicked
off to periodically track a given ip address.
Also made some minor clean up in NeutronL3Adapter, so that it needs not to
duplicate work for tracking ip in the very first iteration. That duplication
is not necessary as the GatewayMacResolverService is already implemented
with thread executors for the periodic monitoring.
Lastly, this gerrit augments the GatewayMacResolver service to provide
an extra boolean param called refreshExternalNetworkBridgeDpidIfNeeded.
That can be used to control whether dpid used gets updated when mac is
not getting resolved.
Change-Id: I95b9e5a2d5773a6be82221b71000ace2a662e772
Signed-off-by: Flavio Fernandes <ffernand@redhat.com>
package org.opendaylight.ovsdb.openstack.netvirt.providers;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.ovsdb.openstack.netvirt.api.*;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ClassifierProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolver;
+import org.opendaylight.ovsdb.openstack.netvirt.api.InboundNatProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.L2ForwardingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.L2RewriteProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.L3ForwardingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.LoadBalancerProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheListener;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.OutboundNatProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestratorImpl;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
-import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.*;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.ArpResponderService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.ClassifierService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.EgressAclService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.InboundNatService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.IngressAclService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.L2ForwardingService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.L2RewriteService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.L3ForwardingService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.LoadBalancerService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.OutboundNatService;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.RoutingService;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.arp.GatewayMacResolverService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
public class ConfigActivator implements BundleActivator {
private static final Logger LOG = LoggerFactory.getLogger(ConfigActivator.class);
private List<ServiceRegistration<?>> registrations = new ArrayList<>();
registerService(context, OutboundNatProvider.class.getName(),
outboundNatService, Service.OUTBOUND_NAT);
- GatewayMacResolverService gatewayMacResolverService = new GatewayMacResolverService();
+ final GatewayMacResolverService gatewayMacResolverService = new GatewayMacResolverService();
registerService(context, GatewayMacResolver.class.getName(),
gatewayMacResolverService, Service.GATEWAY_RESOLVER);
getNotificationProviderService().registerNotificationListener(gatewayMacResolverService);
}
};
networkingProviderManagerTracker.open();
+
+ @SuppressWarnings("unchecked")
+ ServiceTracker ConfigurationServiceTracker = new ServiceTracker(context,
+ ConfigurationService.class, null) {
+ @Override
+ public Object addingService(ServiceReference reference) {
+ LOG.info("addingService ConfigurationService");
+ ConfigurationService service =
+ (ConfigurationService) context.getService(reference);
+ if (service != null) {
+ gatewayMacResolverService.setDependencies(service);
+ }
+ return service;
+ }
+ };
+ ConfigurationServiceTracker.open();
+
+ @SuppressWarnings("unchecked")
+ ServiceTracker NodeCacheManagerTracker = new ServiceTracker(context,
+ NodeCacheManager.class, null) {
+ @Override
+ public Object addingService(ServiceReference reference) {
+ LOG.info("addingService NodeCacheManager");
+ NodeCacheManager service =
+ (NodeCacheManager) context.getService(reference);
+ if (service != null) {
+ gatewayMacResolverService.setDependencies(service);
+ }
+ return service;
+ }
+ };
+ NodeCacheManagerTracker.open();
}
@Override
private final GatewayMacResolverListener gatewayMacResolverListener;
private final Ipv4Address gatewayIpAddress;
- private final Long externalNetworkBridgeDpid;
+ private Long externalNetworkBridgeDpid;
+ private final boolean refreshExternalNetworkBridgeDpidIfNeeded;
private final Ipv4Address arpRequestSourceIp;
private final MacAddress arpRequestSourceMacAddress;
private final boolean periodicRefresh;
public ArpResolverMetadata(final GatewayMacResolverListener gatewayMacResolverListener,
final Long externalNetworkBridgeDpid,
+ final boolean refreshExternalNetworkBridgeDpidIfNeeded,
final Ipv4Address gatewayIpAddress, final Ipv4Address arpRequestSourceIp,
final MacAddress arpRequestMacAddress, final boolean periodicRefresh){
this.gatewayMacResolverListener = gatewayMacResolverListener;
this.externalNetworkBridgeDpid = externalNetworkBridgeDpid;
+ this.refreshExternalNetworkBridgeDpidIfNeeded = refreshExternalNetworkBridgeDpidIfNeeded;
this.gatewayIpAddress = gatewayIpAddress;
this.arpRequestSourceIp = arpRequestSourceIp;
this.arpRequestSourceMacAddress = arpRequestMacAddress;
this.numberOfOutstandingArpRequests = 0;
}
- public RemoveFlowInput getFlowToRemove() {
- return flowToRemove;
+ public boolean isRefreshExternalNetworkBridgeDpidIfNeeded() {
+ return refreshExternalNetworkBridgeDpidIfNeeded;
}
public boolean isPeriodicRefresh() {
return periodicRefresh;
}
+ public RemoveFlowInput getFlowToRemove() {
+ return flowToRemove;
+ }
public void setFlowToRemove(RemoveFlowInput flowToRemove) {
this.flowToRemove = flowToRemove;
}
public Long getExternalNetworkBridgeDpid() {
return externalNetworkBridgeDpid;
}
+ public void setExternalNetworkBridgeDpid(Long externalNetworkBridgeDpid) {
+ this.externalNetworkBridgeDpid = externalNetworkBridgeDpid;
+ }
public Ipv4Address getArpRequestSourceIp() {
return arpRequestSourceIp;
}
public MacAddress getArpRequestSourceMacAddress() {
return arpRequestSourceMacAddress;
}
+ public boolean isGatewayMacAddressResolved() {
+ return gatewayMacAddressResolved;
+ }
/**
* This method is used to determine whether to use the broadcast MAC or the unicast MAC as the destination address
public int hashCode() {
final int prime = 31;
int result = 1;
+
+ result = prime
+ * result
+ + ((gatewayMacResolverListener == null) ? 0 : gatewayMacResolverListener.hashCode());
result = prime
* result
+ ((arpRequestSourceMacAddress == null) ? 0 : arpRequestSourceMacAddress
* result
+ ((gatewayIpAddress == null) ? 0 : gatewayIpAddress.hashCode());
result = prime * result + (periodicRefresh ? 1231 : 1237);
+ result = prime * result + (refreshExternalNetworkBridgeDpidIfNeeded ? 1231 : 1237);
return result;
}
if (getClass() != obj.getClass())
return false;
ArpResolverMetadata other = (ArpResolverMetadata) obj;
+ if (gatewayMacResolverListener == null) {
+ if (other.gatewayMacResolverListener != null)
+ return false;
+ } else if (!gatewayMacResolverListener.equals(other.gatewayMacResolverListener))
+ return false;
if (arpRequestSourceMacAddress == null) {
if (other.arpRequestSourceMacAddress != null)
return false;
return false;
if (periodicRefresh != other.periodicRefresh)
return false;
+ if (refreshExternalNetworkBridgeDpidIfNeeded != other.refreshExternalNetworkBridgeDpidIfNeeded)
+ return false;
return true;
}
*/
package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services.arp;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.math.BigInteger;
-import java.util.Map.Entry;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolver;
import org.opendaylight.ovsdb.openstack.netvirt.api.GatewayMacResolverListener;
+import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider;
import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static com.google.common.base.Preconditions.checkNotNull;
/**
*
private final ScheduledExecutorService gatewayMacRefresherPool = Executors.newScheduledThreadPool(1);
private final ScheduledExecutorService refreshRequester = Executors.newSingleThreadScheduledExecutor();
private AtomicBoolean initializationDone = new AtomicBoolean(false);
+ private volatile ConfigurationService configurationService;
+ private volatile NodeCacheManager nodeCacheManager;
static {
ApplyActions applyActions = new ApplyActionsBuilder().setAction(
if (!gatewayToArpMetadataMap.isEmpty()){
for(final Entry<Ipv4Address, ArpResolverMetadata> gatewayToArpMetadataEntry : gatewayToArpMetadataMap.entrySet()){
final Ipv4Address gatewayIp = gatewayToArpMetadataEntry.getKey();
- final ArpResolverMetadata gatewayMetaData = gatewayToArpMetadataEntry.getValue();
+ final ArpResolverMetadata gatewayMetaData =
+ checkAndGetExternalBridgeDpid(gatewayToArpMetadataEntry.getValue());
gatewayMacRefresherPool.schedule(new Runnable(){
@Override
final Node externalNetworkBridge = getExternalBridge(gatewayMetaData.getExternalNetworkBridgeDpid());
if(externalNetworkBridge == null){
LOG.error("MAC address for gateway {} can not be resolved, because external bridge {} "
- + "is not connected to controller.",gatewayIp.getValue(),gatewayMetaData.getExternalNetworkBridgeDpid() );
+ + "is not connected to controller.",
+ gatewayIp.getValue(),
+ gatewayMetaData.getExternalNetworkBridgeDpid() );
+ } else {
+ LOG.debug("Refresh Gateway Mac for gateway {} using source ip {} and mac {} for ARP request",
+ gatewayIp.getValue(),gatewayMetaData.getArpRequestSourceIp().getValue(),gatewayMetaData.getArpRequestSourceMacAddress().getValue());
+
+ sendGatewayArpRequest(externalNetworkBridge,gatewayIp,gatewayMetaData.getArpRequestSourceIp(), gatewayMetaData.getArpRequestSourceMacAddress());
}
-
- LOG.debug("Refresh Gateway Mac for gateway {} using source ip {} and mac {} for ARP request",
- gatewayIp.getValue(),gatewayMetaData.getArpRequestSourceIp().getValue(),gatewayMetaData.getArpRequestSourceMacAddress().getValue());
-
- sendGatewayArpRequest(externalNetworkBridge,gatewayIp,gatewayMetaData.getArpRequestSourceIp(), gatewayMetaData.getArpRequestSourceMacAddress());
}
}, 1, TimeUnit.SECONDS);
}
* @param sourceIpAddress Source Ip address for the ARP request packet
* @param sourceMacAddress Source Mac address for the ARP request packet
* @param periodicRefresh Enable/Disable periodic refresh of the Gateway Mac address
- * NOTE:Periodic refresh is not supported yet.
* @return Future object
*/
@Override
public ListenableFuture<MacAddress> resolveMacAddress(
final GatewayMacResolverListener gatewayMacResolverListener, final Long externalNetworkBridgeDpid,
+ final Boolean refreshExternalNetworkBridgeDpidIfNeeded,
final Ipv4Address gatewayIp, final Ipv4Address sourceIpAddress, final MacAddress sourceMacAddress,
final Boolean periodicRefresh){
+ Preconditions.checkNotNull(refreshExternalNetworkBridgeDpidIfNeeded);
Preconditions.checkNotNull(sourceIpAddress);
Preconditions.checkNotNull(sourceMacAddress);
Preconditions.checkNotNull(gatewayIp);
}
}else{
gatewayToArpMetadataMap.put(gatewayIp,new ArpResolverMetadata(gatewayMacResolverListener,
- externalNetworkBridgeDpid, gatewayIp,sourceIpAddress,sourceMacAddress,periodicRefresh));
+ externalNetworkBridgeDpid, refreshExternalNetworkBridgeDpidIfNeeded,
+ gatewayIp, sourceIpAddress, sourceMacAddress, periodicRefresh));
}
final Node externalNetworkBridge = getExternalBridge(externalNetworkBridgeDpid);
- if(externalNetworkBridge == null){
- LOG.error("MAC address for gateway {} can not be resolved, because external bridge {} "
- + "is not connected to controller.",gatewayIp.getValue(),externalNetworkBridgeDpid );
+ if (externalNetworkBridge == null) {
+ if (!refreshExternalNetworkBridgeDpidIfNeeded) {
+ LOG.error("MAC address for gateway {} can not be resolved, because external bridge {} "
+ + "is not connected to controller.", gatewayIp.getValue(), externalNetworkBridgeDpid);
+ } else {
+ LOG.debug("MAC address for gateway {} can not be resolved, since dpid was not refreshed yet",
+ gatewayIp.getValue());
+ }
return null;
}
}
private Node getExternalBridge(final Long externalNetworkBridgeDpid){
- final String nodeName = OPENFLOW + externalNetworkBridgeDpid;
+ if (externalNetworkBridgeDpid != null) {
+ final String nodeName = OPENFLOW + externalNetworkBridgeDpid;
+ return getOpenFlowNode(nodeName);
+ }
+ return null;
+ }
+
+ private ArpResolverMetadata checkAndGetExternalBridgeDpid(ArpResolverMetadata gatewayMetaData) {
+ final Long origDpid = gatewayMetaData.getExternalNetworkBridgeDpid();
- return getOpenFlowNode(nodeName);
+ // If we are not allowing dpid to change, there is nothing further to do here
+ if (!gatewayMetaData.isRefreshExternalNetworkBridgeDpidIfNeeded()) {
+ return gatewayMetaData;
+ }
+
+ // If current dpid is null, or if mac is not getting resolved, make an attempt to
+ // grab a different dpid, so a different (or updated) external bridge gets used
+ if (origDpid == null || !gatewayMetaData.isGatewayMacAddressResolved()) {
+ Long newDpid = getAnotherExternalBridgeDpid(origDpid);
+ gatewayMetaData.setExternalNetworkBridgeDpid(newDpid);
+ }
+
+ return gatewayMetaData;
+ }
+
+ private Long getAnotherExternalBridgeDpid(final Long unwantedDpid) {
+ LOG.trace("Being asked to find a new dpid. unwantedDpid:{} cachemanager:{} configurationService:{}",
+ unwantedDpid, nodeCacheManager, configurationService);
+
+ if (nodeCacheManager == null) {
+ LOG.error("Unable to find external dpid to use for resolver: no nodeCacheManager");
+ return unwantedDpid;
+ }
+ if (configurationService == null) {
+ LOG.error("Unable to find external dpid to use for resolver: no configurationService");
+ return unwantedDpid;
+ }
+
+ // Pickup another dpid in list that is different than the unwanted one provided and is in the
+ // operational tree. If none can be found, return the provided dpid as a last resort.
+ // NOTE: We are assuming that all the br-ex are serving one external network and gateway ip of
+ // the external network is reachable from every br-ex
+ // TODO: Consider other deployment scenario, and think of another solution.
+ List<Long> dpids = nodeCacheManager.getBridgeDpids(configurationService.getExternalBridgeName());
+ Collections.shuffle(dpids);
+ for (Long dpid : dpids) {
+ if (dpid == null || dpid.equals(unwantedDpid) || getExternalBridge(dpid) == null) {
+ continue;
+ }
+
+ LOG.debug("Gateway Mac Resolver Service will use dpid {}", dpid);
+ return dpid;
+ }
+
+ LOG.warn("Unable to find usable external dpid for resolver. Best choice is still {}", unwantedDpid);
+ return unwantedDpid;
}
private void sendGatewayArpRequest(final Node externalNetworkBridge,final Ipv4Address gatewayIp,
}
@Override
- public void setDependencies(Object impl) {}
+ public void setDependencies(Object impl) {
+ if (impl instanceof NodeCacheManager) {
+ nodeCacheManager = (NodeCacheManager) impl;
+ } else if (impl instanceof ConfigurationService) {
+ configurationService = (ConfigurationService) impl;
+ }
+ }
@Override
public void stopPeriodicRefresh(Ipv4Address gatewayIp) {
* periodicRefresh flag.
* @param gatewayMacResolverListener An optional listener for mac update callback (can be null)
* @param externalNetworkBridgeDpid This bridge will be used for sending ARP request
+ * @param refreshExternalNetworkBridgeDpidIfNeeded Instructs resolver to change bridge dpid if resolve is failing
* @param gatewayIp ARP request will be send for this ip address
* @param sourceIpAddress Source IP address for the ARP request (localhost)
* @param sourceMacAddress Source MAC address for the ARP request (localhost)
* @param periodicRefresh Do you want to periodically refresh the gateway mac?
* @return ListenableFuture that contains the mac address of gateway ip.
*/
- public ListenableFuture<MacAddress> resolveMacAddress(final GatewayMacResolverListener gatewayMacResolverListener,
- final Long externalNetworkBridgeDpid, final Ipv4Address gatewayIp, final Ipv4Address sourceIpAddress,
+ public ListenableFuture<MacAddress> resolveMacAddress(
+ final GatewayMacResolverListener gatewayMacResolverListener,
+ final Long externalNetworkBridgeDpid, final Boolean refreshExternalNetworkBridgeDpidIfNeeded,
+ final Ipv4Address gatewayIp, final Ipv4Address sourceIpAddress,
final MacAddress sourceMacAddress, final Boolean periodicRefresh);
/**
List<Node> getNodes();
Map<NodeId, Node> getOvsdbNodes();
List<Node> getBridgeNodes();
+ List<Long> getBridgeDpids(final String bridgeName);
void cacheListenerAdded(final ServiceReference ref, NodeCacheListener handler);
void cacheListenerRemoved(final ServiceReference ref);
package org.opendaylight.ovsdb.openstack.netvirt.impl;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
+import com.google.common.base.Preconditions;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
/**
* Neutron L3 Adapter implements a hub-like adapter for the various Neutron events. Based on
private Boolean enabled = false;
private Boolean flgDistributedARPEnabled = true;
private Boolean isCachePopulationDone = false;
- private final ExecutorService gatewayMacResolverPool = Executors.newFixedThreadPool(5);
private Southbound southbound;
private NeutronModelsDataStoreHelper neutronModelsDataStoreHelper;
final boolean isDelete = action == Action.DELETE;
if (neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_GATEWAY)){
- if(!isDelete){
- Node externalBridgeNode = getExternalBridgeNode();
- if(externalBridgeNode != null){
- LOG.info("Port {} is network router gateway interface, "
- + "triggering gateway resolution for the attached external network on node {}", neutronPort, externalBridgeNode);
- this.triggerGatewayMacResolver(externalBridgeNode, neutronPort);
- }else{
- LOG.error("Did not find Node that has external bridge (br-ex), Gateway resolution failed");
- }
+ if (!isDelete) {
+ LOG.info("Port {} is network router gateway interface, "
+ + "triggering gateway resolution for the attached external network", neutronPort);
+ this.triggerGatewayMacResolver(neutronPort);
}else{
NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(neutronPort.getNetworkUUID());
}
private Long getDpidForExternalBridge(Node node) {
- // Check if node is integration bridge; and only then return its dpid
+ // Check if node is external bridge; and only then return its dpid
if (southbound.getBridge(node, configurationService.getExternalBridgeName()) != null) {
return southbound.getDataPathId(node);
}
}
}
- public void triggerGatewayMacResolver(final Node node, final NeutronPort gatewayPort ){
+ private void triggerGatewayMacResolver(final NeutronPort gatewayPort){
- Preconditions.checkNotNull(node);
Preconditions.checkNotNull(gatewayPort);
NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(gatewayPort.getNetworkUUID());
// TODO: address IPv6 case.
if (externalSubnet != null &&
- externalSubnet.getIpVersion() == 4 &&
- gatewayPort.getFixedIPs() != null) {
- LOG.info("Trigger MAC resolution for gateway ip {} on Node {}",externalSubnet.getGatewayIP(),node.getNodeId());
- ListenableFuture<MacAddress> gatewayMacAddress =
- gatewayMacResolver.resolveMacAddress(this,
- getDpidForExternalBridge(node),
- new Ipv4Address(externalSubnet.getGatewayIP()),
- new Ipv4Address(gatewayPort.getFixedIPs().get(0).getIpAddress()),
- new MacAddress(gatewayPort.getMacAddress()),
- true);
- if(gatewayMacAddress != null){
- Futures.addCallback(gatewayMacAddress, new FutureCallback<MacAddress>(){
- @Override
- public void onSuccess(MacAddress result) {
- if(result != null){
- if(!result.getValue().equals(externalRouterMac)){
- updateExternalRouterMac(result.getValue());
- LOG.info("Resolved MAC address for gateway IP {} is {}", externalSubnet.getGatewayIP(),result.getValue());
- }
- }else{
- LOG.warn("MAC address resolution failed for gateway IP {}", externalSubnet.getGatewayIP());
- }
- }
-
- @Override
- public void onFailure(Throwable t) {
- LOG.warn("MAC address resolution failed for gateway IP {}", externalSubnet.getGatewayIP());
- }
- }, gatewayMacResolverPool);
- }
+ externalSubnet.getIpVersion() == 4 &&
+ gatewayPort.getFixedIPs() != null) {
+ LOG.info("Trigger MAC resolution for gateway ip {}", externalSubnet.getGatewayIP());
+
+ gatewayMacResolver.resolveMacAddress(
+ this, /* gatewayMacResolverListener */
+ null, /* externalNetworkBridgeDpid */
+ true, /* refreshExternalNetworkBridgeDpidIfNeeded */
+ new Ipv4Address(externalSubnet.getGatewayIP()),
+ new Ipv4Address(gatewayPort.getFixedIPs().get(0).getIpAddress()),
+ new MacAddress(gatewayPort.getMacAddress()),
+ true /* periodicRefresh */);
} else {
LOG.warn("No gateway IP address found for external network {}", externalNetwork);
}
import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
return nodes;
}
+ @Override
+ public List <Long> getBridgeDpids(final String bridgeName) {
+ List<Long> dpids = Lists.newArrayList();
+ for (Node node : nodeCache.values()) {
+ if (bridgeName == null || southbound.getBridge(node, bridgeName) != null) {
+ long dpid = southbound.getDataPathId(node);
+ if (dpid != 0L) {
+ dpids.add(Long.valueOf(dpid));
+ }
+ }
+ }
+ return dpids;
+ }
+
@Override
public List<Node> getNodes() {
List<Node> nodes = Lists.newArrayList();
}
public String getDatapathId(Node node) {
- String datapathId = null;
OvsdbBridgeAugmentation ovsdbBridgeAugmentation = node.getAugmentation(OvsdbBridgeAugmentation.class);
- if (ovsdbBridgeAugmentation != null && ovsdbBridgeAugmentation.getDatapathId() != null) {
- datapathId = node.getAugmentation(OvsdbBridgeAugmentation.class).getDatapathId().getValue();
- }
- return datapathId;
+ return getDatapathId(ovsdbBridgeAugmentation);
}
public String getDatapathId(OvsdbBridgeAugmentation ovsdbBridgeAugmentation) {