import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private volatile GatewayMacResolver gatewayMacResolver;
private class FloatIpData {
- private final Long dpid; // br-int of node where floating ip is associated with tenant port
- private final Long ofPort; // patch port in br-int used to reach br-ex
- private final String segId; // segmentation id of the net where fixed ip is instantiated
- private final String macAddress; // mac address assigned to neutron port of floating ip
+ // br-int of node where floating ip is associated with tenant port
+ private final Long dpid;
+ // patch port in br-int used to reach br-ex
+ private final Long ofPort;
+ // segmentation id of the net where fixed ip is instantiated
+ private final String segId;
+ // mac address assigned to neutron port of floating ip
+ private final String macAddress;
private final String floatingIpAddress;
- private final String fixedIpAddress; // ip address given to tenant vm
+ // ip address given to tenant vm
+ private final String fixedIpAddress;
private final String neutronRouterMac;
FloatIpData(final Long dpid, final Long ofPort, final String segId, final String macAddress,
}else{
NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(neutronPort.getNetworkUUID());
- if(externalNetwork != null){
- if(externalNetwork.isRouterExternal()){
- final NeutronSubnet externalSubnet = getExternalNetworkSubnet(neutronPort);
- if(externalSubnet != null){
- gatewayMacResolver.stopPeriodicReferesh(new Ipv4Address(externalSubnet.getGatewayIP()));
- }
+ if (externalNetwork != null && externalNetwork.isRouterExternal()) {
+ final NeutronSubnet externalSubnet = getExternalNetworkSubnet(neutronPort);
+ // TODO support IPv6
+ if (externalSubnet != null &&
+ externalSubnet.getIpVersion() == 4) {
+ gatewayMacResolver.stopPeriodicRefresh(new Ipv4Address(externalSubnet.getGatewayIP()));
}
}
}
for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
NeutronRouter_Interface neutronRouterInterface =
new NeutronRouter_Interface(neutronIP.getSubnetUUID(), neutronPort.getPortUUID());
- neutronRouterInterface.setID(neutronIP.getSubnetUUID()); // id of router interface to be same as subnet
+ // id of router interface to be same as subnet
+ neutronRouterInterface.setID(neutronIP.getSubnetUUID());
neutronRouterInterface.setTenantID(neutronPort.getTenantID());
this.handleNeutronRouterInterfaceEvent(null /*neutronRouter*/, neutronRouterInterface, action);
// need to do this check here because a router interface is not added to a node until tenant becomes needed
// there.
//
- if (!isDelete) {
+ if (!isDelete && neutronPort.getFixedIPs() != null) {
for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
NeutronRouter_Interface neutronRouterInterface =
subnetIdToRouterInterfaceCache.get(neutronIP.getSubnetUUID());
}
this.updateL3ForNeutronPort(neutronPort, currPortShouldBeDeleted);
}
+
+ if (isDelete) {
+ /*
+ * Bug 4277: Remove the router interface cache only after deleting the neutron port l3 flows.
+ */
+ this.cleanupRouterCache(neutronRouterInterface);
+ }
}
/**
// this.programFlowsForFloatingIP(neutronFloatingIP, action == Action.DELETE);
if (action != Action.DELETE) {
- programFlowsForFloatingIPArpAdd(neutronFloatingIP); // must be first, as it updates floatIpDataMapCache
+ // must be first, as it updates floatIpDataMapCache
+ programFlowsForFloatingIPArpAdd(neutronFloatingIP);
programFlowsForFloatingIPInbound(neutronFloatingIP, Action.ADD);
programFlowsForFloatingIPOutbound(neutronFloatingIP, Action.ADD);
programFlowsForFloatingIPOutbound(neutronFloatingIP, Action.DELETE);
programFlowsForFloatingIPInbound(neutronFloatingIP, Action.DELETE);
- programFlowsForFloatingIPArpDelete(neutronFloatingIP.getID()); // must be last, as it updates floatIpDataMapCache
+ // must be last, as it updates floatIpDataMapCache
+ programFlowsForFloatingIPArpDelete(neutronFloatingIP.getID());
}
}
// will look at desired action for node.
final String cacheKey = node.getNodeId().getValue() + ":" + providerSegmentationId + ":" + ipStr;
- final Boolean isProgrammed = l3ForwardingCache.contains(cacheKey);
+ final boolean isProgrammed = l3ForwardingCache.contains(cacheKey);
- if (actionForNode == Action.DELETE && isProgrammed == Boolean.FALSE) {
+ if (actionForNode == Action.DELETE && !isProgrammed) {
LOG.trace("programL3ForwardingStage1 for node {} providerId {} mac {} ip {} action {} is already done",
node.getNodeId().getValue(), providerSegmentationId, macAddress, ipStr, actionForNode);
return;
}
- if (actionForNode == Action.ADD && isProgrammed == Boolean.TRUE) {
+ if (actionForNode == Action.ADD && isProgrammed) {
LOG.trace("programL3ForwardingStage1 for node {} providerId {} mac {} ip {} action {} is already done",
node.getNodeId().getValue(), providerSegmentationId, macAddress, ipStr, actionForNode);
return;
}
}
- // Keep cache for finding router's mac from network uuid -- remove
- //
- if (isDelete) {
- networkIdToRouterMacCache.remove(neutronNetwork.getNetworkUUID());
- networkIdToRouterIpListCache.remove(neutronNetwork.getNetworkUUID());
- subnetIdToRouterInterfaceCache.remove(subnet.getSubnetUUID());
- }
+ // Keep cache for finding router's mac from network uuid -- NOTE: remove is done later, via cleanupRouterCache()
}
private void programFlowForNetworkFromExternal(final Node node,
final String cacheKey = node.getNodeId().getValue() + ":" +
sourceSegmentationId + ":" + destinationSegmentationId + ":" +
ipStr + "/" + Integer.toString(mask);
- final Boolean isProgrammed = routerInterfacesCache.contains(cacheKey);
+ final boolean isProgrammed = routerInterfacesCache.contains(cacheKey);
- if (actionForNode == Action.DELETE && isProgrammed == Boolean.FALSE) {
+ if (actionForNode == Action.DELETE && !isProgrammed) {
LOG.trace("programRouterInterfaceStage1 for node {} sourceSegId {} destSegId {} mac {} ip {} mask {}" +
" action {} is already done",
node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
macAddress, ipStr, mask, actionForNode);
return;
}
- if (actionForNode == Action.ADD && isProgrammed == Boolean.TRUE) {
+ if (actionForNode == Action.ADD && isProgrammed) {
LOG.trace("programRouterInterfaceStage1 for node {} sourceSegId {} destSegId {} mac {} ip {} mask {}" +
" action {} is already done",
node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
// will look at desired action for node.
//
final String cacheKey = dpid + ":" + segOrOfPort + ":" + ipStr;
- final Boolean isProgrammed = staticArpEntryCache.contains(cacheKey);
+ final boolean isProgrammed = staticArpEntryCache.contains(cacheKey);
- if (action == Action.DELETE && isProgrammed == Boolean.FALSE) {
+ if (action == Action.DELETE && !isProgrammed) {
LOG.trace("programStaticArpStage1 dpid {} segOrOfPort {} mac {} ip {} action {} is already done",
dpid, segOrOfPort, macAddress, ipStr, action);
return true;
}
- if (action == Action.ADD && isProgrammed == Boolean.TRUE) {
+ if (action == Action.ADD && isProgrammed) {
LOG.trace("programStaticArpStage1 dpid {} segOrOfPort {} mac {} ip {} action {} is already done",
dpid, segOrOfPort, macAddress, ipStr, action);
return true;
// will look at desired action for node.
//
final String cacheKey = dpid + ":" + inboundOFPort + ":" + providerSegmentationId + ":" + matchAddress;
- final Boolean isProgrammed = inboundIpRewriteCache.contains(cacheKey);
+ final boolean isProgrammed = inboundIpRewriteCache.contains(cacheKey);
- if (action == Action.DELETE && isProgrammed == Boolean.FALSE) {
+ if (action == Action.DELETE && !isProgrammed) {
LOG.trace("programInboundIpRewriteStage1 dpid {} OFPort {} seg {} matchAddress {} rewriteAddress {}" +
" action {} is already done",
dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action);
return true;
}
- if (action == Action.ADD && isProgrammed == Boolean.TRUE) {
+ if (action == Action.ADD && isProgrammed) {
LOG.trace("programInboundIpRewriteStage1 dpid {} OFPort {} seg {} matchAddress {} rewriteAddress {}" +
" action is already done",
dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action);
// will look at desired action for node.
//
final String cacheKey = node.getNodeId().getValue() + ":" + providerSegmentationId + ":" + cidr;
- final Boolean isProgrammed = outboundIpRewriteExclusionCache.contains(cacheKey);
+ final boolean isProgrammed = outboundIpRewriteExclusionCache.contains(cacheKey);
- if (actionForRewriteExclusion == Action.DELETE && isProgrammed == Boolean.FALSE) {
+ if (actionForRewriteExclusion == Action.DELETE && !isProgrammed) {
LOG.trace("programIpRewriteExclusionStage1 node {} providerId {} cidr {} action {} is already done",
node.getNodeId().getValue(), providerSegmentationId, cidr, actionForRewriteExclusion);
return;
}
- if (actionForRewriteExclusion == Action.ADD && isProgrammed == Boolean.TRUE) {
+ if (actionForRewriteExclusion == Action.ADD && isProgrammed) {
LOG.trace("programIpRewriteExclusionStage1 node {} providerId {} cidr {} action {} is already done",
node.getNodeId().getValue(), providerSegmentationId, cidr, actionForRewriteExclusion);
return;
// will look at desired action for node.
//
final String cacheKey = fid.dpid + ":" + fid.segId + ":" + fid.fixedIpAddress;
- final Boolean isProgrammed = outboundIpRewriteCache.contains(cacheKey);
+ final boolean isProgrammed = outboundIpRewriteCache.contains(cacheKey);
- if (action == Action.DELETE && isProgrammed == Boolean.FALSE) {
+ if (action == Action.DELETE && !isProgrammed) {
LOG.trace("programOutboundIpRewriteStage1 dpid {} seg {} fixedIpAddress {} floatIp {} action {} " +
"is already done",
fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action);
return;
}
- if (action == Action.ADD && isProgrammed == Boolean.TRUE) {
+ if (action == Action.ADD && isProgrammed) {
LOG.trace("programOutboundIpRewriteStage1 dpid {} seg {} fixedIpAddress {} floatIp {} action {} " +
"is already done",
fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action);
}
private NeutronSubnet getExternalNetworkSubnet(NeutronPort gatewayPort){
- NeutronSubnet extSubnet = null;
- for (NeutronSubnet subnet : neutronSubnetCache.getAllSubnets()){
- if(subnet.getPortsInSubnet().contains(gatewayPort)){
- extSubnet = subnet;
- break;
+ for (Neutron_IPs neutronIPs : gatewayPort.getFixedIPs()) {
+ String subnetUUID = neutronIPs.getSubnetUUID();
+ NeutronSubnet extSubnet = neutronSubnetCache.getSubnet(subnetUUID);
+ if (extSubnet != null && extSubnet.getGatewayIP() != null) {
+ return extSubnet;
}
+ if (extSubnet == null) {
+ // TODO: when subnet is created, try again.
+ LOG.debug("subnet {} in not found", subnetUUID);
+ }
}
- return extSubnet;
+ return null;
}
+ private void cleanupRouterCache(final NeutronRouter_Interface neutronRouterInterface) {
+ /*
+ * Fix for 4277
+ * Remove the router cache only after deleting the neutron
+ * port l3 flows.
+ */
+ final NeutronPort neutronPort = neutronPortCache.getPort(neutronRouterInterface.getPortUUID());
+
+ if (neutronPort != null) {
+ networkIdToRouterMacCache.remove(neutronPort.getNetworkUUID());
+ networkIdToRouterIpListCache.remove(neutronPort.getNetworkUUID());
+ subnetIdToRouterInterfaceCache.remove(neutronRouterInterface.getSubnetUUID());
+ }
+ }
+
public void triggerGatewayMacResolver(final Node node, final NeutronPort gatewayPort ){
Preconditions.checkNotNull(node);
if(externalNetwork != null){
if(externalNetwork.isRouterExternal()){
final NeutronSubnet externalSubnet = getExternalNetworkSubnet(gatewayPort);
- if(externalSubnet != null){
- if(externalSubnet.getGatewayIP() != null){
- LOG.info("Trigger MAC resolution for gateway ip {} on Node {}", externalSubnet.getGatewayIP(), node.getNodeId());
-
- ListenableFuture<MacAddress> gatewayMacAddress =
- gatewayMacResolver.resolveMacAddress(getDpidForExternalBridge(node),
- new Ipv4Address(externalSubnet.getGatewayIP()),
- new Ipv4Address(gatewayPort.getFixedIPs().get(0).getIpAddress()),
- new MacAddress(gatewayPort.getMacAddress()),
- false);
- if(gatewayMacAddress != null){
- Futures.addCallback(gatewayMacAddress, new FutureCallback<MacAddress>(){
- @Override
- public void onSuccess(MacAddress result) {
- if(result != null){
+
+ // TODO: address IPv6 case.
+ if (externalSubnet != null &&
+ externalSubnet.getIpVersion() == 4) {
+ LOG.info("Trigger MAC resolution for gateway ip {} on Node {}",externalSubnet.getGatewayIP(),node.getNodeId());
+ ListenableFuture<MacAddress> gatewayMacAddress =
+ gatewayMacResolver.resolveMacAddress(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());
+ LOG.info("Resolved MAC address for gateway IP {} is {}", externalSubnet.getGatewayIP(),result.getValue());
}
- }
-
- @Override
- public void onFailure(Throwable t) {
+ }else{
LOG.warn("MAC address resolution failed for gateway IP {}", externalSubnet.getGatewayIP());
}
- }, gatewayMacResolverPool);
- }
- }else{
- LOG.warn("No gateway IP address found for external subnet {}", externalSubnet);
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LOG.warn("MAC address resolution failed for gateway IP {}", externalSubnet.getGatewayIP());
+ }
+ }, gatewayMacResolverPool);
}
- }else{
- LOG.warn("Neutron subnet not found for external network {}", externalNetwork);
+ } else {
+ LOG.warn("No gateway IP address found for external network {}", externalNetwork);
}
}
}else{
}
@Override
- public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
+ public void setDependencies(ServiceReference serviceReference) {
tenantNetworkManager =
(TenantNetworkManager) ServiceHelper.getGlobalInstance(TenantNetworkManager.class, this);
configurationService =