X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=neutron-mapper%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fgroupbasedpolicy%2Fneutron%2Fmapper%2Fmapping%2FNeutronPortAware.java;h=368699ddaf02db78419d56c475d8dc4fed89e591;hb=refs%2Fchanges%2F29%2F60029%2F3;hp=45fdaa65e50306063415429dcce9f895adca0eaf;hpb=c2ab14065d51ccd7b2ae82aedd6aadf8b0f7d881;p=groupbasedpolicy.git diff --git a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java index 45fdaa65e..368699dda 100644 --- a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java +++ b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java @@ -10,603 +10,762 @@ package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping; import static com.google.common.base.Preconditions.checkNotNull; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import javax.annotation.Nullable; import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.ReadTransaction; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper; -import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory; +import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFactory; +import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory; +import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator; +import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.MetadataService; +import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkClient; +import org.opendaylight.groupbasedpolicy.neutron.mapper.infrastructure.NetworkService; import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils; -import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils.ForwardingCtx; -import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils; -import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils; -import org.opendaylight.neutron.spi.INeutronPortAware; -import org.opendaylight.neutron.spi.NeutronPort; -import org.opendaylight.neutron.spi.NeutronSecurityGroup; -import org.opendaylight.neutron.spi.NeutronSecurityRule; -import org.opendaylight.neutron.spi.Neutron_IPs; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; +import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils; +import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils; +import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; +import org.opendaylight.groupbasedpolicy.util.IidFactory; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.base.endpoints.by.ports.BaseEndpointByPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPortBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.base.endpoints.PortByBaseEndpointKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpoint; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ports.by.endpoints.PortByEndpointBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet; -import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Function; import com.google.common.base.Optional; -import com.google.common.base.Strings; -import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; -public class NeutronPortAware implements INeutronPortAware { +public class NeutronPortAware implements NeutronAware { - public static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class); - private static final String DEVICE_OWNER_DHCP = "network:dhcp"; - private static final String DEVICE_OWNER_ROUTER_IFACE = "network:router_interface"; - private static final String DEVICE_OWNER_ROUTER_GATEWAY = "network:router_gateway"; - private static final String DEVICE_OWNER_FLOATING_IP = "network:floatingip"; - private static final int DHCP_CLIENT_PORT = 68; - private static final int DHCP_SERVER_PORT = 67; + private static final Logger LOG = LoggerFactory.getLogger(NeutronPortAware.class); + public static final InstanceIdentifier PORT_WILDCARD_IID = + InstanceIdentifier.builder(Neutron.class).child(Ports.class).child(Port.class).build(); private final DataBroker dataProvider; - private final EndpointService epService; + private final EndpointRegistrator epRegistrator; + private final IpPrefix metadataIpPrefix; - public NeutronPortAware(DataBroker dataProvider, EndpointService epService) { + public NeutronPortAware(DataBroker dataProvider, EndpointRegistrator epRegistrator, + @Nullable IpPrefix metadataIpPrefix) { this.dataProvider = checkNotNull(dataProvider); - this.epService = checkNotNull(epService); + this.epRegistrator = checkNotNull(epRegistrator); + this.metadataIpPrefix = checkNotNull(metadataIpPrefix); } - /** - * @see org.opendaylight.neutron.spi.INeutronPortAware#canCreatePort(org.opendaylight.neutron.spi.NeutronPort) - */ - @Override - public int canCreatePort(NeutronPort port) { - LOG.trace("canCreatePort - {}", port); - // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints. - List fixedIPs = port.getFixedIPs(); - if (fixedIPs != null && fixedIPs.size() > 1) { - LOG.warn("Neutron mapper does not support multiple IPs on the same port."); - return StatusCode.BAD_REQUEST; - } - return StatusCode.OK; + @Override public void onCreated(Port createdItem, Neutron neutron) { + onCreated(createdItem, neutron, true); } - /** - * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortCreated(org.opendaylight.neutron.spi.NeutronPort) - */ - @Override - public void neutronPortCreated(NeutronPort port) { - LOG.trace("neutronPortCreated - {}", port); - if (isRouterInterfacePort(port)) { - LOG.trace("Port is router interface - {} does nothing. {} handles router iface.", - NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName()); - return; - } - if (isRouterGatewayPort(port)) { - LOG.trace("Port is router gateway - {}", port.getID()); - return; - } - if (isFloatingIp(port)) { - LOG.trace("Port is floating ip - {}", port.getID()); - return; - } - if (Strings.isNullOrEmpty(port.getTenantID())) { - LOG.trace("REMOVE ME: Tenant is null - {}", port.getID()); - return; - } - ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); - TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID())); - if (isDhcpPort(port)) { - LOG.trace("Port is DHCP port. - {}", port.getID()); - List dhcpSecRules = createDhcpSecRules(port, null, rwTx); - if (dhcpSecRules == null) { - rwTx.cancel(); + public void onCreated(Port port, Neutron neutron, boolean addBaseEpMapping) { + LOG.trace("created port - {}", port); + if (PortUtils.isRouterInterfacePort(port)) { + LOG.trace("Port is router interface port: {}", port.getUuid().getValue()); + // router interface port can have only one IP + Optional potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port); + if (!potentialPortIpWithSubnet.isPresent()) { + LOG.warn("Illegal state - router interface port does not contain fixed IPs {}", + port); return; } - - for (NeutronSecurityRule dhcpSecRule : dhcpSecRules) { - boolean isDhcpSecRuleAdded = NeutronSecurityRuleAware.addNeutronSecurityRule(dhcpSecRule, rwTx); - if (!isDhcpSecRuleAdded) { - rwTx.cancel(); + FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get(); + ContextId routerL3Context = new ContextId(port.getDeviceId()); + ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); + AddressEndpointKey addrEpKey = new AddressEndpointKey(port.getMacAddress().getValue(), + MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN); + UniqueId portId = new UniqueId(port.getUuid().getValue()); + addBaseEndpointMappings(addrEpKey, portId, rwTx); + // Add Qrouter and VPProuter port as Endpoint + if (port.getAugmentation(PortBindingExtension.class) != null && + PortUtils.DEVICE_VIF_TYPE.equals(port.getAugmentation(PortBindingExtension.class).getVifType())) { + LOG.trace("Port is QRouter port: {}", port.getUuid().getValue()); + Optional firstFixedIps = PortUtils.resolveFirstFixedIps(port); + if (!firstFixedIps.isPresent()) { + LOG.warn("QRouter port does not have an IP address. {}", port); return; } + FixedIps ipWithSubnet = firstFixedIps.get(); + NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue()); + List epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups()); + epgsFromSecGroups.add(NetworkService.EPG_ID); + // BUILD BASE ENDPOINT + AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(port, networkContainment, + epgsFromSecGroups); + AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(port, networkContainment, + epgsFromSecGroups, neutron); + setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp); + // BUILD ENDPOINT + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder + epInBuilder = + createEndpointRegFromPort( + port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron); + registerBaseEndpointAndStoreMapping( + ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx, addBaseEpMapping); + registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx); } - } else { - List secGroups = port.getSecurityGroups(); - if (secGroups != null) { - for (NeutronSecurityGroup secGroup : secGroups) { - EndpointGroupId epgId = new EndpointGroupId(secGroup.getSecurityGroupUUID()); - Optional potentialEpg = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, - IidFactory.endpointGroupIid(tenantId, epgId), rwTx); - if (!potentialEpg.isPresent()) { - boolean isSecGroupCreated = NeutronSecurityGroupAware.addNeutronSecurityGroup(secGroup, rwTx); - if (!isSecGroupCreated) { - rwTx.cancel(); - return; - } - if (containsSecRuleWithRemoteSecGroup(secGroup)) { - List dhcpSecRules = createDhcpSecRules(port, epgId, rwTx); - if (dhcpSecRules == null) { - rwTx.cancel(); - return; - } - List routerSecRules = NeutronRouterAware.createRouterSecRules(port, epgId, rwTx); - if (routerSecRules == null) { - rwTx.cancel(); - return; - } - } - } else { - List secRules = secGroup.getSecurityRules(); - if (secRules != null) { - for (NeutronSecurityRule secRule : secRules) { - NeutronSecurityRuleAware.addNeutronSecurityRule(secRule, rwTx); - } - } - } - } + // change L3Context for all EPs with same subnet as router port + changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), neutron); + // set L3Context as parent for bridge domain which is parent of subnet + TenantId tenantId = new TenantId(port.getTenantId().getValue()); + Optional potentialRouterPortSubnet = SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(), neutron.getSubnets()); + if (!potentialRouterPortSubnet.isPresent()) { + LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}", + port); + return; } - } - - boolean isNeutronPortCreated = addNeutronPort(port, rwTx, epService); - if (!isNeutronPortCreated) { - rwTx.cancel(); - return; - } - - DataStoreHelper.submitToDs(rwTx); - } - - public static boolean addNeutronPort(NeutronPort port, ReadWriteTransaction rwTx, EndpointService epService) { - TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID())); - L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID()); - ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rwTx); - boolean isFwCtxValid = validateForwardingCtx(fwCtx); - if (!isFwCtxValid) { - return false; - } - EndpointKey epKey = new EndpointKey(fwCtx.getL2BridgeDomain().getId(), new MacAddress(port.getMacAddress())); - UniqueId portId = new UniqueId(port.getID()); - EndpointByPort endpointByPort = createEndpointByPort(epKey, portId); - rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointByPortIid(portId), endpointByPort, true); - PortByEndpoint portByEndpoint = createPortByEndpoint(portId, epKey); - rwTx.put(LogicalDatastoreType.OPERATIONAL, - IidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint, true); - - try { - RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx); - - RpcResult rpcResult = epService.registerEndpoint(registerEpRpcInput).get(); - if (!rpcResult.isSuccessful()) { - LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput); - return false; + Subnet routerPortSubnet = potentialRouterPortSubnet.get(); + ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue()); + ForwardingContext l2Bd = new ForwardingContextBuilder().setContextId(l2BdId) + .setContextType(MappingUtils.L2_BRDIGE_DOMAIN) + .setParent(MappingUtils.createParent(routerL3Context, MappingUtils.L3_CONTEXT)) + .build(); + rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true); + // set virtual router IP for subnet + NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(routerPortSubnet, neutron, null); + rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain); + + // does the same for tenant forwarding domains + processTenantForwarding(routerPortSubnet, routerL3Context, portIpWithSubnet, tenantId, rwTx); + + DataStoreHelper.submitToDs(rwTx); + } else if (PortUtils.isDhcpPort(port)) { + // process as normal port but put it to DHCP group + LOG.trace("Port is DHCP port: {}", port.getUuid().getValue()); + Optional firstFixedIps = PortUtils.resolveFirstFixedIps(port); + if (!firstFixedIps.isPresent()) { + LOG.warn("DHCP port does not have an IP address. {}", port); + return; } - } catch (InterruptedException | ExecutionException e) { - LOG.error("addPort - RPC invocation failed.", e); - return false; - } - return true; - } - - private static boolean validateForwardingCtx(ForwardingCtx fwCtx) { - if (fwCtx.getL2FloodDomain() == null) { - LOG.warn("Illegal state - l2-flood-domain does not exist."); - return false; - } - if (fwCtx.getL2BridgeDomain() == null) { - LOG.warn("Illegal state - l2-bridge-domain does not exist."); - return false; - } - if (fwCtx.getL3Context() == null) { - LOG.warn("Illegal state - l3-context does not exist."); - return false; + FixedIps ipWithSubnet = firstFixedIps.get(); + NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue()); + List epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups()); + epgsFromSecGroups.add(NetworkService.EPG_ID); + AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(port, networkContainment, + Collections.emptyList()); + AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(port, networkContainment, + epgsFromSecGroups, neutron); + + setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp); + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createEndpointRegFromPort( + port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron); + ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); + registerBaseEndpointAndStoreMapping( + ImmutableList.of(l3BaseEp.build(), l2BaseEp.build()), port, rwTx, addBaseEpMapping); + registerMetadataServiceForDhcpPort(port, neutron, l2BaseEp, rwTx, true); + registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx); + DataStoreHelper.submitToDs(rwTx); + } else if (PortUtils.isNormalPort(port)) { + LOG.trace("Port is normal port: {}", port.getUuid().getValue()); + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = null; + AddressEndpointRegBuilder l2BaseEp; + AddressEndpointRegBuilder l3BaseEp = null; + Optional firstFixedIps = PortUtils.resolveFirstFixedIps(port); + List epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups()); + epgsFromSecGroups.add(NetworkClient.EPG_ID); + if (firstFixedIps.isPresent()) { + // endpoint has only one network containment therefore only first IP is used + FixedIps ipWithSubnet = firstFixedIps.get(); + NetworkDomainId containment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue()); + epInBuilder = createEndpointRegFromPort(port, ipWithSubnet, containment, epgsFromSecGroups, neutron); + l2BaseEp = createBasicMacAddrEpInputBuilder(port, + containment, epgsFromSecGroups); + l3BaseEp = createBasicL3AddrEpInputBuilder(port, containment, epgsFromSecGroups, neutron); + setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp); + } else { + NetworkDomainId containment = new NetworkDomainId(port.getNetworkId().getValue()); + epInBuilder = createEndpointRegFromPort(port, null, containment, epgsFromSecGroups, neutron); + l2BaseEp = createBasicMacAddrEpInputBuilder(port, containment, epgsFromSecGroups); + } + List baseEpRegs = new ArrayList<>(); + baseEpRegs.add(l2BaseEp.build()); + if (l3BaseEp != null) { + baseEpRegs.add(l3BaseEp.build()); + } + ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); + registerBaseEndpointAndStoreMapping(baseEpRegs, port, rwTx, addBaseEpMapping); + registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx); + DataStoreHelper.submitToDs(rwTx); + } else if (PortUtils.isRouterGatewayPort(port)) { + // do nothing because actual trigger is attaching of port to router + LOG.trace("Port is router gateway port: {}", port.getUuid().getValue()); + } else if (PortUtils.isFloatingIpPort(port)) { + // do nothing because trigger is floating IP + LOG.trace("Port is floating ip: {}", port.getUuid().getValue()); + } else { + LOG.warn("Unknown port: {}", port); } - return true; } - private static EndpointByPort createEndpointByPort(EndpointKey epKey, UniqueId portId) { - return new EndpointByPortBuilder().setPortId(portId) - .setL2Context(epKey.getL2Context()) - .setMacAddress(epKey.getMacAddress()) - .build(); + private Port cloneMetadataPortFromDhcpPort(Port port, IpPrefix metadataPrefix) { + IpAddress metadataIp = MappingUtils.ipPrefixToIpAddress(metadataPrefix); + List metadataIps = port.getFixedIps().stream().map(fi -> { + FixedIpsKey key = new FixedIpsKey(metadataIp, fi.getKey().getSubnetId()); + return new FixedIpsBuilder(fi).setKey(key).setIpAddress(metadataIp).build(); + }).collect(Collectors.toList()); + return new PortBuilder(port).setFixedIps(metadataIps).build(); } - private static PortByEndpoint createPortByEndpoint(UniqueId portId, EndpointKey epKey) { - return new PortByEndpointBuilder().setPortId(portId) - .setL2Context(epKey.getL2Context()) - .setMacAddress(epKey.getMacAddress()) - .build(); - } - - private List createDhcpSecRules(NeutronPort port, EndpointGroupId consumerEpgId, ReadTransaction rTx) { - TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID())); - Neutron_IPs firstIp = MappingUtils.getFirstIp(port.getFixedIPs()); - if (firstIp == null) { - LOG.warn("Illegal state - DHCP port does not have an IP address."); - return null; + private void registerMetadataServiceForDhcpPort(Port port, Neutron neutron, AddressEndpointRegBuilder childEpToAdd, + ReadWriteTransaction rwTx, boolean registerMapping) { + Optional resolveNetworkContainment = PortUtils.resolveNetworkContainment(port); + if (!resolveNetworkContainment.isPresent()) { + LOG.warn("DHCP port does not have an IP address. {}", port); + return; } - SubnetId dhcpSubnetId = new SubnetId(firstIp.getSubnetUUID()); - Optional potentialSubnet = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, - IidFactory.subnetIid(tenantId, dhcpSubnetId), rTx); - if (!potentialSubnet.isPresent()) { - LOG.warn("Illegal state - Subnet {} where is DHCP port does not exist.", dhcpSubnetId.getValue()); - return null; + AddressEndpointRegBuilder metadataEp = + createBasicL3AddrEpInputBuilder(cloneMetadataPortFromDhcpPort(port, metadataIpPrefix), + resolveNetworkContainment.get(), Lists.newArrayList(MetadataService.EPG_ID), neutron); + AddressEndpointKey aek = new AddressEndpointKey(metadataEp.getAddress(), metadataEp.getAddressType(), + metadataEp.getContextId(), metadataEp.getContextType()); + Optional optMetadataEp = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek), rwTx); + if (!optMetadataEp.isPresent()) { + setParentChildRelationshipForEndpoints(metadataEp, childEpToAdd); + } else { + List childs = optMetadataEp.get().getChildEndpoint(); + childs.add(createChildEndpoint(childEpToAdd)); + metadataEp.setChildEndpoint(childs); } - IpPrefix ipSubnet = potentialSubnet.get().getIpPrefix(); - NeutronSecurityRule dhcpRuleEgress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, true); - NeutronSecurityRule dhcpRuleIngress = createDhcpSecRule(port.getID(), tenantId, ipSubnet, consumerEpgId, false); - return ImmutableList.of(dhcpRuleEgress, dhcpRuleIngress); + registerBaseEndpointAndStoreMapping(ImmutableList.of(metadataEp.build()), port, rwTx, registerMapping); } - private NeutronSecurityRule createDhcpSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet, EndpointGroupId consumerEpgId, - boolean isEgress) { - NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule(); - dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_DHCP_ID.getValue()); - dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue()); - dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet)); - if (consumerEpgId != null) { - dhcpSecRule.setSecurityRemoteGroupID(consumerEpgId.getValue()); - } - if (isEgress) { - dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "__" + ruleUuid); - dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS); - dhcpSecRule.setSecurityRulePortMin(DHCP_CLIENT_PORT); - dhcpSecRule.setSecurityRulePortMax(DHCP_CLIENT_PORT); - } else { - dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "__" + ruleUuid); - dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS); - dhcpSecRule.setSecurityRulePortMin(DHCP_SERVER_PORT); - dhcpSecRule.setSecurityRulePortMax(DHCP_SERVER_PORT); - } - dhcpSecRule.setSecurityRuleProtocol(NeutronUtils.UDP); - if (ipSubnet.getIpv4Prefix() != null) { - dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4); - } else { - dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6); - } - return dhcpSecRule; + private void setParentChildRelationshipForEndpoints(AddressEndpointRegBuilder parentEp, + AddressEndpointRegBuilder childEp) { + childEp.setParentEndpointChoice(new ParentEndpointCaseBuilder().setParentEndpoint( + ImmutableList.of(createParentEndpoint(parentEp))).build()); + parentEp.setChildEndpoint(ImmutableList.of(createChildEndpoint(childEp))); } - /** - * @see org.opendaylight.neutron.spi.INeutronPortAware#canUpdatePort(org.opendaylight.neutron.spi.NeutronPort, - * org.opendaylight.neutron.spi.NeutronPort) - */ - @Override - public int canUpdatePort(NeutronPort delta, NeutronPort original) { - LOG.trace("canUpdatePort - delta: {} original: {}", delta, original); - if (delta.getFixedIPs() == null || delta.getFixedIPs().isEmpty()) { - return StatusCode.OK; - } - // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints. - List fixedIPs = delta.getFixedIPs(); - if (fixedIPs != null && fixedIPs.size() > 1) { - LOG.warn("Neutron mapper does not support multiple IPs on the same port."); - return StatusCode.BAD_REQUEST; - } - return StatusCode.OK; + @Deprecated + private void processTenantForwarding(Subnet routerPortSubnet, ContextId routerL3Context, FixedIps portIpWithSubnet, + TenantId tenantId, ReadWriteTransaction rwTx) { + L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue()); + L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(new L3ContextId(routerL3Context)).build(); + rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true); + // set virtual router IP for subnet + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet subnet = NeutronSubnetAware.createTenantSubnet( + routerPortSubnet, portIpWithSubnet.getIpAddress()); + rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, subnet.getId()), subnet); } /** - * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortUpdated(org.opendaylight.neutron.spi.NeutronPort) + * Registers endpoint from {@link Port} and method parameters. + * Always creates registration input for L2 endpoint. + * Creates registration input for L3 endpoint if fixedIps argument is not null. */ - @Override - public void neutronPortUpdated(NeutronPort port) { - LOG.trace("neutronPortUpdated - {}", port); - if (isRouterInterfacePort(port)) { - LOG.trace("Port is router interface - {} does nothing. {} handles router iface.", - NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName()); - return; - } - if (isRouterGatewayPort(port)) { - LOG.trace("Port is router gateway - {}", port.getID()); - return; - } - if (isFloatingIp(port)) { - LOG.trace("Port is floating ip - {}", port.getID()); - return; - } - if (Strings.isNullOrEmpty(port.getTenantID())) { - LOG.trace("REMOVE ME: Tenant is null - {}", port.getID()); - return; - } - - ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction(); - TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID())); - MacAddress macAddress = new MacAddress(port.getMacAddress()); - L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID()); - ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx); - boolean isFwCtxValid = validateForwardingCtx(fwCtx); - if (!isFwCtxValid) { - rTx.close(); - return; - } + @Deprecated + private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createEndpointRegFromPort( + Port port, FixedIps fixedIps, NetworkDomainId networkContainment, List endpointGroupIds, Neutron neutron) { + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createBasicEndpointInputBuilder( + port).setNetworkContainment(networkContainment); + if (fixedIps != null) { + L3Address l3Address = resolveL3AddressFromPort(port, fixedIps, neutron); + epInBuilder.setL3Address(ImmutableList.of(l3Address)); + } + epInBuilder.setEndpointGroups(endpointGroupIds); + return epInBuilder; + } - Optional potentionalEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, - IidFactory.endpointIid(fwCtx.getL2BridgeDomain().getId(), macAddress), rTx); - if (!potentionalEp.isPresent()) { - LOG.warn("Illegal state - endpoint {} does not exist.", new EndpointKey(fwCtx.getL2BridgeDomain().getId(), - macAddress)); - rTx.close(); + private void changeL3ContextForEpsInSubnet(Uuid subnetUuid, Neutron neutron) { + if (neutron == null) { + LOG.debug("No new data are written, there is no L3 context in subnet {} to update", subnetUuid); return; } - - Endpoint ep = potentionalEp.get(); - if (isEpIpDifferentThanPortFixedIp(ep, port) || isEpgDifferentThanSecGrp(ep, port)) { - UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(ep); - RegisterEndpointInput registerEpRpcInput = createRegisterEndpointInput(port, fwCtx); - try { - RpcResult rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get(); - if (!rpcResult.isSuccessful()) { - LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput); - rTx.close(); - return; - } - rpcResult = epService.registerEndpoint(registerEpRpcInput).get(); - if (!rpcResult.isSuccessful()) { - LOG.warn("Illegal state - RPC registerEndpoint failed. Input of RPC: {}", registerEpRpcInput); - rTx.close(); - return; + java.util.Optional optSubnet = neutron.getSubnets() + .getSubnet() + .stream() + .filter(subnet -> subnet.getNetworkId() != null && subnet.getUuid().getValue().equals(subnetUuid.getValue())) + .findAny(); + if (!optSubnet.isPresent()) { + LOG.error("Failed to update metadata endpoint in subnet {}. Could not resolve Network ID", subnetUuid); + } else { + AddressEndpointUnreg metadataEpUnreg = + new AddressEndpointUnregBuilder().setAddress(String.valueOf(metadataIpPrefix.getValue())) + .setAddressType(IpPrefixType.class) + .setContextId(new ContextId(optSubnet.get().getNetworkId().getValue())) + .setContextType(MappingUtils.L3_CONTEXT) + .build(); + epRegistrator.unregisterEndpoint(metadataEpUnreg); + } + Set portsInSameSubnet = PortUtils.findPortsBySubnet(subnetUuid, neutron.getPorts()); + for (Port portInSameSubnet : portsInSameSubnet) { + if (PortUtils.isNormalPort(portInSameSubnet) || PortUtils.isDhcpPort(portInSameSubnet) + || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) { + // endpoints are created only from neutron normal port or DHCP port + Optional firstFixedIps = PortUtils.resolveFirstFixedIps(portInSameSubnet); + if (firstFixedIps.isPresent()) { + // endpoint has only one network containment therefore only first IP is used + FixedIps ipWithSubnet = firstFixedIps.get(); + List endpointGroupIds = new ArrayList<>(); + if (PortUtils.isDhcpPort(portInSameSubnet) || PortUtils.isQrouterOrVppRouterPort(portInSameSubnet)) { + endpointGroupIds.add(NetworkService.EPG_ID); + } else if (PortUtils.isNormalPort(portInSameSubnet)) { + endpointGroupIds.add(NetworkClient.EPG_ID); + } + NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue()); + AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(portInSameSubnet, + networkContainment, endpointGroupIds); + AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(portInSameSubnet, + networkContainment, endpointGroupIds, neutron); + setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp); + AddressEndpointUnreg addrEpUnreg = new AddressEndpointUnregBuilder().setAddress(l3BaseEp.getAddress()) + .setAddressType(l3BaseEp.getAddressType()) + .setContextId(new ContextId(portInSameSubnet.getNetworkId().getValue())) + .setContextType(l3BaseEp.getContextType()) + .build(); + epRegistrator.unregisterEndpoint(addrEpUnreg); + RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder() + .setAddressEndpointReg(ImmutableList.of(l2BaseEp.build(), l3BaseEp.build())).build(); + epRegistrator.registerEndpoint(regBaseEpInput); + if(PortUtils.isDhcpPort(portInSameSubnet)) { + ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); + registerMetadataServiceForDhcpPort(portInSameSubnet, neutron, l2BaseEp, rwTx, false); + try { + rwTx.submit().get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to update metadata endpoint for DHCP port {}. {}", portInSameSubnet, e); + } + } + modifyL3ContextForEndpoints(portInSameSubnet, ipWithSubnet, l3BaseEp.getContextId()); } - } catch (InterruptedException | ExecutionException e) { - LOG.error("addPort - RPC invocation failed.", e); - rTx.close(); - return; } } - rTx.close(); } - private boolean isEpIpDifferentThanPortFixedIp(Endpoint ep, NeutronPort port) { - List l3Addresses = ep.getL3Address(); - List fixedIPs = port.getFixedIPs(); - if ((l3Addresses == null || l3Addresses.isEmpty()) && (fixedIPs == null || fixedIPs.isEmpty())) { - return false; - } - if (l3Addresses != null && !l3Addresses.isEmpty() && fixedIPs != null && !fixedIPs.isEmpty()) { - if (fixedIPs.get(0).getIpAddress().equals(Utils.getStringIpAddress(l3Addresses.get(0).getIpAddress()))) { - return false; - } - } - return true; + private ChildEndpoint createChildEndpoint(AddressEndpointRegBuilder builder) { + return new ChildEndpointBuilder().setAddress(builder.getAddress()) + .setAddressType(builder.getAddressType()) + .setContextId(builder.getContextId()) + .setContextType(builder.getContextType()) + .build(); } - private boolean isEpgDifferentThanSecGrp(Endpoint ep, NeutronPort port) { - List epgIds = ep.getEndpointGroups(); - List secGroups = port.getSecurityGroups(); - if ((epgIds == null || epgIds.isEmpty()) && (secGroups == null || secGroups.isEmpty())) { - return false; - } - if (epgIds != null && !epgIds.isEmpty() && secGroups != null && !secGroups.isEmpty()) { - if (epgIds.size() != secGroups.size()) { - return true; - } - Collection epgIdsFromSecGroups = Collections2.transform(secGroups, - new Function() { + private ParentEndpoint createParentEndpoint(AddressEndpointRegBuilder builder) { + return new ParentEndpointBuilder().setAddress(builder.getAddress()) + .setAddressType(builder.getAddressType()) + .setContextId(builder.getContextId()) + .setContextType(builder.getContextType()) + .build(); + } - @Override - public EndpointGroupId apply(NeutronSecurityGroup input) { - return new EndpointGroupId(input.getSecurityGroupUUID()); - } - }); - // order independent equals - Set one = new HashSet<>(epgIds); - Set two = new HashSet<>(epgIdsFromSecGroups); - if (one.equals(two)) { - return false; - } - } - return true; + @Deprecated + private void modifyL3ContextForEndpoints(Port port, FixedIps resolvedPortFixedIp, ContextId newContextId) { + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createBasicEndpointInputBuilder(port); + epInBuilder.setNetworkContainment(new NetworkDomainId(resolvedPortFixedIp.getSubnetId().getValue())); + L3Address l3Address = new L3AddressBuilder().setL3Context(new L3ContextId(newContextId)) + .setIpAddress(resolvedPortFixedIp.getIpAddress()) + .build(); + epInBuilder.setL3Address(ImmutableList.of(l3Address)); + List epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups()); + epgsFromSecGroups.add(NetworkClient.EPG_ID); + epInBuilder.setEndpointGroups(epgsFromSecGroups); + epRegistrator.registerEndpoint(epInBuilder.build()); + // unregister L3EP + L3ContextId oldL3Context = new L3ContextId(port.getNetworkId().getValue()); + L3 l3 = new L3Builder().setL3Context(oldL3Context).setIpAddress(resolvedPortFixedIp.getIpAddress()).build(); + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput epUnreg = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder().setL3( + ImmutableList.of(l3)) + .build(); + epRegistrator.unregisterEndpoint(epUnreg); } - /** - * @see org.opendaylight.neutron.spi.INeutronPortAware#canDeletePort(org.opendaylight.neutron.spi.NeutronPort) - */ - @Override - public int canDeletePort(NeutronPort port) { - LOG.trace("canDeletePort - {}", port); - // nothing to consider - return StatusCode.OK; + private AddressEndpointRegBuilder createBasicMacAddrEpInputBuilder(Port port, + NetworkDomainId networkContainment, @Nullable List endpointGroupsToAdd) { + AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class) + .setAddress(port.getMacAddress().getValue()) + .setAddressType(MacAddressType.class) + .setContextType(MappingUtils.L2_BRDIGE_DOMAIN) + .setContextId(new ContextId(port.getNetworkId().getValue())) + .setTenant(new TenantId(port.getTenantId().getValue())) + .setTimestamp(System.currentTimeMillis()); + List epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd); + addrEpbuilder.setEndpointGroup(epgs); + if (networkContainment != null) { + addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder().setContainment( + new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment) + .setNetworkDomainType(MappingUtils.SUBNET) + .build()).build()); + } + return addrEpbuilder; } - /** - * @see org.opendaylight.neutron.spi.INeutronPortAware#neutronPortDeleted(org.opendaylight.neutron.spi.NeutronPort) - */ - @Override - public void neutronPortDeleted(NeutronPort port) { - LOG.trace("neutronPortDeleted - {}", port); - if (isRouterInterfacePort(port)) { - LOG.trace("Port is router interface - {} does nothing. {} handles router iface.", - NeutronPortAware.class.getSimpleName(), NeutronRouterAware.class.getSimpleName()); - return; - } - ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction(); - TenantId tenantId = new TenantId(Utils.normalizeUuid(port.getTenantID())); - L2FloodDomainId l2FdId = new L2FloodDomainId(port.getNetworkUUID()); - ForwardingCtx fwCtx = MappingUtils.createForwardingContext(tenantId, l2FdId, rTx); - boolean isFwCtxValid = validateForwardingCtx(fwCtx); - if (!isFwCtxValid) { - rTx.close(); - return; - } + private AddressEndpointRegBuilder createBasicL3AddrEpInputBuilder(Port port, NetworkDomainId networkContainment, + @Nullable List endpointGroupsToAdd, Neutron neutron) { + Optional firstFixedIps = PortUtils.resolveFirstFixedIps(port); + if (!firstFixedIps.isPresent()) { + throw new IllegalStateException("Failed to resolve FixedIps for port " + port.getKey() + + ". Cannot register L3 Address endpoint."); + } + ContextId resolveL3ContextForPort = resolveL3ContextForPort(port, port.getFixedIps().get(0), neutron); + + AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder().setAddressType(MacAddressType.class) + .setAddress(MappingUtils.ipAddressToStringIpPrefix(firstFixedIps.get().getIpAddress())) + .setAddressType(IpPrefixType.class) + .setContextType(MappingUtils.L3_CONTEXT) + .setContextId(resolveL3ContextForPort) + .setTenant(new TenantId(port.getTenantId().getValue())) + .setTimestamp(System.currentTimeMillis()); + List epgs = concatEndpointGroups(port.getSecurityGroups(), endpointGroupsToAdd); + addrEpbuilder.setEndpointGroup(epgs); + if (networkContainment != null) { + addrEpbuilder.setNetworkContainment(new NetworkContainmentBuilder().setContainment( + new NetworkDomainContainmentBuilder().setNetworkDomainId(networkContainment) + .setNetworkDomainType(MappingUtils.SUBNET) + .build()).build()); + } + return addrEpbuilder; + } - UnregisterEndpointInput unregisterEpRpcInput = createUnregisterEndpointInput(port, fwCtx); - try { - RpcResult rpcResult = epService.unregisterEndpoint(unregisterEpRpcInput).get(); - if (!rpcResult.isSuccessful()) { - LOG.warn("Illegal state - RPC unregisterEndpoint failed. Input of RPC: {}", unregisterEpRpcInput); + private List concatEndpointGroups(List securityGroups, + @Nullable List endpointGroupsToAdd) { + List epgs = new ArrayList<>(); + if (securityGroups != null) { + for (Uuid sgId : securityGroups) { + epgs.add(new EndpointGroupId(sgId.getValue())); } - } catch (InterruptedException | ExecutionException e) { - LOG.error("addPort - RPC invocation failed.", e); - } finally { - rTx.close(); } + if (endpointGroupsToAdd != null) { + epgs.addAll(endpointGroupsToAdd); + } + return epgs; } - private static RegisterEndpointInput createRegisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) { - List epgIds = new ArrayList<>(); - // each EP has to be in EPG ANY, except dhcp and router - if (isDhcpPort(port)) { - epgIds.add(MappingUtils.EPG_DHCP_ID); - } else if (!containsSecRuleWithRemoteSecGroup(port.getSecurityGroups())) { - epgIds.add(MappingUtils.EPG_ANY_ID); - } + @Deprecated + private static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder createBasicEndpointInputBuilder( + Port port) { + return new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder().setL2Context( + new L2BridgeDomainId(port.getNetworkId().getValue())) + .setMacAddress(new MacAddress(port.getMacAddress().getValue())) + .setTenant(new TenantId(port.getTenantId().getValue())) + .setTimestamp(System.currentTimeMillis()); + } - List securityGroups = port.getSecurityGroups(); + private static List resolveEpgIdsFromSecGroups(@Nullable List securityGroups) { + List epgIds = new ArrayList<>(); if ((securityGroups == null || securityGroups.isEmpty())) { - if (!isDhcpPort(port)) { - LOG.warn( - "Port {} does not contain any security group. The port should belong to 'default' security group at least.", - port.getPortUUID()); - } - } else { - for (NeutronSecurityGroup secGrp : securityGroups) { - epgIds.add(new EndpointGroupId(secGrp.getSecurityGroupUUID())); - } + return epgIds; } - RegisterEndpointInputBuilder inputBuilder = new RegisterEndpointInputBuilder().setL2Context( - fwCtx.getL2BridgeDomain().getId()) - .setMacAddress(new MacAddress(port.getMacAddress())) - .setTenant(new TenantId(Utils.normalizeUuid(port.getTenantID()))) - .setEndpointGroups(epgIds) - .addAugmentation(OfOverlayContextInput.class, - new OfOverlayContextInputBuilder().setPortName(createTapPortName(port)).build()) - .setTimestamp(System.currentTimeMillis()); - List fixedIPs = port.getFixedIPs(); - // TODO Li msunal this getting of just first IP has to be rewrite when OFOverlay renderer - // will support l3-endpoints. Then we will register L2 and L3 endpoints separately. - Neutron_IPs firstIp = MappingUtils.getFirstIp(fixedIPs); - if (firstIp != null) { - inputBuilder.setNetworkContainment(new SubnetId(firstIp.getSubnetUUID())); - L3Address l3Address = new L3AddressBuilder().setIpAddress(Utils.createIpAddress(firstIp.getIpAddress())) - .setL3Context(fwCtx.getL3Context().getId()) - .build(); - inputBuilder.setL3Address(ImmutableList.of(l3Address)); + for (Uuid secGrp : securityGroups) { + epgIds.add(new EndpointGroupId(secGrp.getValue())); } - if (!Strings.isNullOrEmpty(port.getName())) { + return epgIds; + } + @Deprecated + private void registerEndpointAndStoreMapping( + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput regEpInput, + Port port, ReadWriteTransaction rwTx) { + boolean isRegisteredEndpoint = epRegistrator.registerEndpoint(regEpInput); + if (!isRegisteredEndpoint) { + LOG.error("Failed to register endpoint: {}", regEpInput); + return; } - return inputBuilder.build(); + UniqueId portId = new UniqueId(port.getUuid().getValue()); + EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress( + port.getMacAddress().getValue())); + LOG.trace("Adding Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getUuid() + .getValue(), port.getDeviceOwner(), epKey); + EndpointByPort endpointByPort = MappingFactory.createEndpointByPort(epKey, portId); + rwTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.endpointByPortIid(portId), endpointByPort, true); + PortByEndpoint portByEndpoint = MappingFactory.createPortByEndpoint(portId, epKey); + rwTx.put(LogicalDatastoreType.OPERATIONAL, + NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), portByEndpoint, + true); } - private static boolean containsSecRuleWithRemoteSecGroup(List secGroups) { - if (secGroups == null) { - return false; + @Deprecated + private void unregisterEndpointAndRemoveMapping( + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput unregEpInput, + Port port, ReadWriteTransaction rwTx) { + boolean isUnregisteredEndpoint = epRegistrator.unregisterEndpoint(unregEpInput); + if (isUnregisteredEndpoint) { + UniqueId portId = new UniqueId(port.getUuid().getValue()); + EndpointKey epKey = new EndpointKey(new L2BridgeDomainId(port.getNetworkId().getValue()), new MacAddress( + port.getMacAddress().getValue())); + LOG.trace("Removing Port-Endpoint mapping for port {} (device owner {}) and endpoint {}", port.getUuid() + .getValue(), port.getDeviceOwner(), epKey); + DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, + NeutronGbpIidFactory.endpointByPortIid(portId), rwTx); + DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, + NeutronGbpIidFactory.portByEndpointIid(epKey.getL2Context(), epKey.getMacAddress()), rwTx); } - for (NeutronSecurityGroup secGroup : secGroups) { - boolean containsSecRuleWithRemoteSecGroup = containsSecRuleWithRemoteSecGroup(secGroup); - if (containsSecRuleWithRemoteSecGroup) { - return true; - } - } - return false; } - private static boolean containsSecRuleWithRemoteSecGroup(NeutronSecurityGroup secGroup) { - List secRules = secGroup.getSecurityRules(); - if (secRules == null) { - return false; + private void registerBaseEndpointAndStoreMapping(List addrEpRegs, Port port, + WriteTransaction wTx, boolean addBaseEpMappings) { + RegisterEndpointInput regBaseEpInput = new RegisterEndpointInputBuilder().setAddressEndpointReg(addrEpRegs) + .build(); + + boolean isRegisteredBaseEndpoint = epRegistrator.registerEndpoint(regBaseEpInput); + if (!isRegisteredBaseEndpoint) { + LOG.error("Failed to register address endpoint: {}", addrEpRegs); + return; } - for (NeutronSecurityRule secRule : secRules) { - if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) { - return true; + for (AddressEndpointReg addrEpReg : addrEpRegs) { + if (MappingUtils.L2_BRDIGE_DOMAIN.equals(addrEpReg.getContextType()) && addBaseEpMappings) { + UniqueId portId = new UniqueId(port.getUuid().getValue()); + LOG.trace("Adding Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}", + port.getUuid()); + AddressEndpointKey addrEpKey = new AddressEndpointKey(addrEpReg.getAddress(), + addrEpReg.getAddressType(), addrEpReg.getContextId(), addrEpReg.getContextType()); + addBaseEndpointMappings(addrEpKey, portId, wTx); } } - return false; } - private static Name createTapPortName(NeutronPort port) { - return new Name("tap" + port.getID().substring(0, 11)); + private void addBaseEndpointMappings(AddressEndpointKey addrEpKey, UniqueId portId, WriteTransaction wTx) { + BaseEndpointByPort baseEndpointByPort = MappingFactory.createBaseEndpointByPort(addrEpKey, portId); + wTx.put(LogicalDatastoreType.OPERATIONAL, NeutronGbpIidFactory.baseEndpointByPortIid(portId), + baseEndpointByPort, true); + PortByBaseEndpoint portByBaseEndpoint = MappingFactory.createPortByBaseEndpoint(portId, addrEpKey); + wTx.put(LogicalDatastoreType.OPERATIONAL, + NeutronGbpIidFactory.portByBaseEndpointIid(new PortByBaseEndpointKey( + portByBaseEndpoint.getKey())), portByBaseEndpoint, true); } - private static boolean isDhcpPort(NeutronPort port) { - return DEVICE_OWNER_DHCP.equals(port.getDeviceOwner()); + private void unregisterEndpointAndRemoveMapping(UnregisterEndpointInput baseEpUnreg, Port port, + ReadWriteTransaction rwTx, boolean removeBaseEpMappings) { + boolean isUnregisteredBaseEndpoint = epRegistrator.unregisterEndpoint(baseEpUnreg); + if (isUnregisteredBaseEndpoint) { + UniqueId portId = new UniqueId(port.getUuid().getValue()); + PortByBaseEndpointKey portByBaseEndpointKey = new PortByBaseEndpointKey(port.getMacAddress().getValue(), + MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN); + LOG.trace("Removing Port-BaseEndpoint mapping for port {} (device owner {}) and endpoint {}", + port.getUuid().getValue(), port.getDeviceOwner(), portByBaseEndpointKey); + if (removeBaseEpMappings) { + removeBaseEndpointMappings(portByBaseEndpointKey, portId, rwTx); + } + } } - private static boolean isRouterInterfacePort(NeutronPort port) { - return DEVICE_OWNER_ROUTER_IFACE.equals(port.getDeviceOwner()); + private void removeBaseEndpointMappings(PortByBaseEndpointKey portByBaseEndpointKey, UniqueId portId, ReadWriteTransaction rwTx) { + DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, + NeutronGbpIidFactory.baseEndpointByPortIid(portId), rwTx); + DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL, + NeutronGbpIidFactory.portByBaseEndpointIid(portByBaseEndpointKey), rwTx); } - private static boolean isRouterGatewayPort(NeutronPort port) { - return DEVICE_OWNER_ROUTER_GATEWAY.equals(port.getDeviceOwner()); + @Override + public void onUpdated(Port oldPort, Port newPort, Neutron oldNeutron, Neutron newNeutron) { + LOG.trace("updated port - OLD: {}\nNEW: {}", oldPort, newPort); + onDeleted(oldPort, oldNeutron, newNeutron, false); + onCreated(newPort, newNeutron, false); } - private static boolean isFloatingIp(NeutronPort port) { - return DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner()); + @Override public void onDeleted(Port deletedItem, Neutron oldNeutron, Neutron newNeutron) { + onDeleted(deletedItem, oldNeutron, newNeutron, true); } - private UnregisterEndpointInput createUnregisterEndpointInput(Endpoint ep) { - UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder(); - L2 l2Ep = new L2Builder().setL2Context(ep.getL2Context()).setMacAddress(ep.getMacAddress()).build(); - inputBuilder.setL2(ImmutableList.of(l2Ep)); - // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints. - // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should - // be registered separately. - if (ep.getL3Address() != null && !ep.getL3Address().isEmpty()) { - List l3Eps = new ArrayList<>(); - for (L3Address ip : ep.getL3Address()) { - l3Eps.add(new L3Builder().setL3Context(ip.getL3Context()).setIpAddress(ip.getIpAddress()).build()); + public void onDeleted(Port port, Neutron oldNeutron, Neutron newNeutron, boolean removeBaseEpMapping) { + LOG.trace("deleted port - {}", port); + if (PortUtils.isRouterInterfacePort(port)) { + LOG.trace("Port is router interface port: {}", port.getUuid().getValue()); + // router interface port can have only one IP + Optional potentialPortIpWithSubnet = PortUtils.resolveFirstFixedIps(port); + if (!potentialPortIpWithSubnet.isPresent()) { + LOG.warn("Illegal state - router interface port does not contain fixed IPs {}", + port); + return; } - inputBuilder.setL3(l3Eps); + FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get(); + L3ContextId l3Context = new L3ContextId(port.getNetworkId().getValue()); + // change L3Context for all new EPs with same subnet as router port + changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), newNeutron); + // set L3Context as parent for bridge domain which is parent of subnet + TenantId tenantId = new TenantId(port.getTenantId().getValue()); + Optional potentialRouterPortSubnet = SubnetUtils.findSubnet(portIpWithSubnet.getSubnetId(), + oldNeutron.getSubnets()); + if (!potentialRouterPortSubnet.isPresent()) { + LOG.warn("Illegal state - router interface port is in subnet which does not exist. {}", port); + return; + } + ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); + Subnet routerPortSubnet = potentialRouterPortSubnet.get(); + modifyForwardingOnDelete(routerPortSubnet, l3Context, tenantId, rwTx); + ContextId l2BdId = new ContextId(routerPortSubnet.getNetworkId().getValue()); + ForwardingContext fwdCtx = new ForwardingContextBuilder().setContextId(l2BdId) + .setContextType(MappingUtils.L2_BRDIGE_DOMAIN) + .setParent(MappingUtils.createParent(l3Context, MappingUtils.L3_CONTEXT)) + .build(); + rwTx.merge(LogicalDatastoreType.CONFIGURATION, + L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx); + NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron, null); + rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()), + subnet); + unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx); + unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping); + DataStoreHelper.submitToDs(rwTx); + } else if (PortUtils.isDhcpPort(port)) { + LOG.trace("Port is DHCP port: {}", port.getUuid().getValue()); + ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); + unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx); + unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping); + DataStoreHelper.submitToDs(rwTx); + } else if (PortUtils.isNormalPort(port)) { + LOG.trace("Port is normal port: {}", port.getUuid().getValue()); + ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction(); + unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx); + unregisterEndpointAndRemoveMapping(createUnregisterBaseEndpointInput(port, oldNeutron), port, rwTx, removeBaseEpMapping); + DataStoreHelper.submitToDs(rwTx); + } else if (PortUtils.isRouterGatewayPort(port)) { + // do nothing because actual trigger is detaching of port from router + LOG.trace("Port is router gateway port: {}", port.getUuid().getValue()); + } else if (PortUtils.isFloatingIpPort(port)) { + // do nothing because trigger is floating IP + LOG.trace("Port is floating ip: {}", port.getUuid().getValue()); + } else { + LOG.warn("Unknown port: {}", port); } - return inputBuilder.build(); } - private UnregisterEndpointInput createUnregisterEndpointInput(NeutronPort port, ForwardingCtx fwCtx) { + @Deprecated + private void modifyForwardingOnDelete(Subnet routerPortSubnet, L3ContextId l3contextId, TenantId tenantId, ReadWriteTransaction rwTx) { + L2BridgeDomainId l2BdId = new L2BridgeDomainId(routerPortSubnet.getNetworkId().getValue()); + L2BridgeDomain l2Bd = new L2BridgeDomainBuilder().setId(l2BdId).setParent(l3contextId).build(); + rwTx.merge(LogicalDatastoreType.CONFIGURATION, IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd); + // remove virtual router IP for subnet + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet tenantSubnet = NeutronSubnetAware.createTenantSubnet(routerPortSubnet, null); + rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subnetIid(tenantId, tenantSubnet.getId()), tenantSubnet); + } + + private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput createUnregisterBaseEndpointInput( + Port port, Neutron neutron) { UnregisterEndpointInputBuilder inputBuilder = new UnregisterEndpointInputBuilder(); - L2 l2Ep = new L2Builder().setL2Context(fwCtx.getL2BridgeDomain().getId()) - .setMacAddress(new MacAddress(port.getMacAddress())) + List list = new ArrayList<>(); + AddressEndpointUnregBuilder addrL2EpUnregBuilder = new AddressEndpointUnregBuilder(); + addrL2EpUnregBuilder.setAddress(port.getMacAddress().getValue()) + .setAddressType(MacAddressType.class) + .setContextId(new ContextId(port.getNetworkId().getValue())) + .setContextType(MappingUtils.L2_BRDIGE_DOMAIN); + list.add(addrL2EpUnregBuilder.build()); + Optional potentialFirstIp = PortUtils.resolveFirstFixedIps(port); + if (potentialFirstIp.isPresent()) { + ContextId l3ContextId = resolveL3ContextForPort(port, potentialFirstIp.get(), neutron); + AddressEndpointUnregBuilder addrL3EpUnregBuilder = new AddressEndpointUnregBuilder(); + addrL3EpUnregBuilder.setAddress(MappingUtils.ipAddressToStringIpPrefix(potentialFirstIp.get().getIpAddress())) + .setAddressType(IpPrefixType.class) + .setContextId(l3ContextId) + .setContextType(L3Context.class); + list.add(addrL3EpUnregBuilder.build()); + } + inputBuilder.setAddressEndpointUnreg(list); + return inputBuilder.build(); + } + + @Deprecated + private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput createUnregisterEndpointInput( + Port port, Neutron neutron) { + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder inputBuilder = + new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder(); + L2 l2Ep = new L2Builder().setL2Context(new L2BridgeDomainId(port.getNetworkId().getValue())) + .setMacAddress(new MacAddress(port.getMacAddress().getValue())) .build(); inputBuilder.setL2(ImmutableList.of(l2Ep)); - // TODO Li msunal this has to be rewrite when OFOverlay renderer will support l3-endpoints. - // Endpoint probably will not have l3-addresses anymore, because L2 and L3 endpoints should - // be registered separately. - if (port.getFixedIPs() != null && !port.getFixedIPs().isEmpty()) { - inputBuilder.setL3(createL3s(port.getFixedIPs(), fwCtx.getL3Context().getId())); + // we've registered EP with only first IP so remove only EP with first IP + Optional potentialFirstIp = PortUtils.resolveFirstFixedIps(port); + if (potentialFirstIp.isPresent()) { + FixedIps firstIp = potentialFirstIp.get(); + L3Address l3Address = resolveL3AddressFromPort(port, firstIp, neutron); + L3 l3 = new L3Builder().setIpAddress(l3Address.getIpAddress()) + .setL3Context(l3Address.getL3Context()) + .build(); + inputBuilder.setL3(ImmutableList.of(l3)); } return inputBuilder.build(); } - private List createL3s(List neutronIps, L3ContextId l3ContextId) { - List l3s = new ArrayList<>(); - for (Neutron_IPs fixedIp : neutronIps) { - String ip = fixedIp.getIpAddress(); - L3 l3 = new L3Builder().setIpAddress(Utils.createIpAddress(ip)).setL3Context(l3ContextId).build(); - l3s.add(l3); + @Deprecated + private static L3Address resolveL3AddressFromPort(Port port, FixedIps portFixedIPs, Neutron neutron) { + Set routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts()); + for (Port routerIfacePort : routerIfacePorts) { + Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId(); + // if port is in the same subnet as router interface then we want to use L3Context of + // router + if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) { + L3ContextId epL3ContextId = new L3ContextId(routerIfacePort.getDeviceId()); + LOG.trace("Router interface port was found in the same subnet as port have {}", port); + return new L3AddressBuilder().setL3Context(epL3ContextId) + .setIpAddress(portFixedIPs.getIpAddress()) + .build(); + } } - return l3s; + return new L3AddressBuilder().setL3Context(new L3ContextId(port.getNetworkId().getValue())) + .setIpAddress(portFixedIPs.getIpAddress()) + .build(); } + private static ContextId resolveL3ContextForPort(Port port, FixedIps portFixedIPs, Neutron neutron) { + Set routerIfacePorts = PortUtils.findRouterInterfacePorts(neutron.getPorts()); + for (Port routerIfacePort : routerIfacePorts) { + Uuid routerIfacePortSubnet = routerIfacePort.getFixedIps().get(0).getSubnetId(); + // if port is in the same subnet as router interface then we want to use L3Context of + // router + if (portFixedIPs.getSubnetId().equals(routerIfacePortSubnet)) { + LOG.trace("Router interface port was found in the same subnet as port have {}", port); + return new ContextId(routerIfacePort.getDeviceId()); + } + } + return new ContextId(port.getNetworkId().getValue()); + } }